Is there any good practice (pattern) in turning asynchronous calls into synchronous?
I have a third party library who's methods are all asynchronos, to get result of almoust any method you must listen to an event, which will bring some context with it.
basically it looks like:
service.BeginSomething(...);
service.OnBeginSomethingCompleted += ;
what I need is to execute some code after BeginSomething when it is really complete (thus after OnBeginSomethingCompleted is triggered). It is very inconvinient to handle the response in the event.
The only way I could think of is running a Thread.Sleep loop and wait till some field on the form is updated, but it doesn't look like very elegant sollution.
I'm using .net 4.0.
As other said, if possible you should try to make your own code async. If that won't work, does your third-party library support the standard
BeginXXX
,EndXXX
async pattern? If so, then using the TPL would make things easy for you. Your code will look something like this:The specific overload you'll want to use will depend on how many parameters you need to pass. You can see the list here.
You might want to look at Reactive Extensions
With Rx you can wrap that into an 'event' basically - the do something like
someClass.SomeEvent.Subscribe(d=>...)
to subscribe using usually some lambda expression to handle what you need. Also useObserveOn
to handle it on the GUI thread (see the details, this is just a hint).Other option is to use
async await
(which is now available for use with VS 2010).hope this helps
NOTE: Rx have a native support for async methods and turning them into Rx events with pretty much just one call. Take a look at
Observable.FromAsyncPattern
FromAsyncPatternUse a
ManualResetEvent
. In your sync wrapper create it, then pass it to theservice.BeginSomething()
call as part of the state object. Immediately after the call,WaitOne()
on it, this will block.In the
service.OnBeginSomethingCompleted
event extract it from the state object and set it, this will unblock the sync caller.The general trend of modern software development (on Windows platform too) is to run, what is possible asynchroniously.
Actually from Windows8 software design guidelines, if the code runs more then 50ms, it has to be asynchronious.
So I would not suggest to block the thread, but instead benefit from that library and provide to the user with some nice looking animation saying "wait, responce comming", or something like this, or some progress bar.
In short, do not block thread, notify a user about what is going on in app and leave it async.
If
BeginSomething()
returns anIAsyncResult
(like a delegate's.BeginInvoke
would do), you can get theWaitHandle
from that:By the way, by assigning the event handler after starting the async process, you are introducing a race condition where the async call may complete before the event is registered, causing it to never fire.
This solution is similar to Brian Gideon's, but I think a little bit cleaner for what you're trying to do. It uses the Monitor object to cause the calling thread to wait until the Completed event is triggered.