I was running into similar problems where my service would make an async call to the Business layer an then wait for an event to fire back on the service. Whenver the event fired the Callback context was lost. I have not delved into the details of why this is but i ended up implementing a workaround of essentially storing a reference to the currentcontext and firing off a seperate Thread to call the to call the business layer and once it is complete fire the callback with the reference i have stored.
1) Create new class that would contain both my input request and a refence to the callback eg.
public struct MyCallbackDetails {
public MyCallbackDetails(IMyServiceCallback callback, RequestType request) : this()
Callback = callback;
Request = request;
}
public IMyServiceCallback Callback { get; set; }
public RequestType request { get; set; }
}
2) Then i would fire off a seperate thread passing a MyCallbackDetails object instead of just the request:
public ResponseType MyServiceMethod(RequestType request) {
//...Do Some Stuff
//Create MyCallbackDetails object to store reference to the callback and keep channel open
MyCallDetails callDetails = new MyCallDetails(OperationContext.Current.GetCallbackChannel<IMyServiceCallback>(), request);
//Fire off a new thread to call the BL and do some work
Thread processThread = new Thread(RunCallbackMethod);
processThread.Start(callDetails);
}
3) And my RunCallbackMethod would make the BL call and respond with a callback.
void RunCallBackMethod(Object requestDetails)
{
//Use callbackdetails to make BL calls
MyCallbackDetails callDetails = (MyCallbackDetails)requestDetails;
// Make BL call - all code under here is syncrhonous
ResponseType response = BusinessLayer.BusinessMethod(callDetails.Request);
//NB: If your responsetype is a business object you will need to convert it to a service object
callDetails.Callback.SomeMethod(results);
}
NB: Yes i have now done away with having an event from my Business Layer fire back to the Service Layer however as i am firing off a seperate thread for the Business Layer it still runs asynchronously and acts the same as if i was calling the BL directly in an ASync manner and waiting for an event to notify its completion.
PS: Thanks to Rory for the idea and most of the code to implement this.