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.

Is there a status property on the service object that can be checked for completion? So you can sleep the thread until the status = "done" or whatever.
–
scott.korinApr 12 '12 at 13:29

The async CTP in C# 5 will make this trivial, and look, syntactically, like synchronous code. It's still in beta right now though.
–
ServyApr 12 '12 at 13:31

Better to change your mind set and write you client so it works this way too. Do you really need a thread to wait?
–
JodrellApr 12 '12 at 13:32

I'm not sure that async/awayit would help in this case. I've made only a brief look at it, but as far as I understood to use it, the library should have been specifically created for such use?
–
Georgy SmirnovApr 12 '12 at 13:55

+1; looks like a good solution for a library that isn't following normal patterns and practices.
–
Adam RobinsonApr 12 '12 at 15:15

@Brian, regardign your update - luckely it is solved in the library: each method allows to send the context that would be returned in the event, also once executed, method returns unique number of the operation, which is also returned in the event.
–
Georgy SmirnovApr 13 '12 at 8:23

@GeorgySmirnov: Perfect, you can just key off that in the event handler to know whether or not to call complete.Set().
–
Brian GideonApr 13 '12 at 13:01

Thank you, it looks like something that could be helpful, though to use it I would probably need to wrap it into some kind of library.
–
Georgy SmirnovApr 12 '12 at 13:52

This is what I meant by 'sync wrapper'. I'd definitly create a SyncSomething.dll consuming your Something.dll and have the app only consume the sync version. E.g. static constructor of your wrapper class would set up the OnXXXCompleted handlers once and for all.
–
Eugen RieckApr 12 '12 at 13:56

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:

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.

+1. As long as there's a corresponding EndSomething call that actually gets the result (rather than the result only being passed through the completed event's eventargs), then this is certainly the approach that requires the least amount of change.
–
Adam RobinsonApr 12 '12 at 13:40

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 use ObserveOn 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.FromAsyncPatternFromAsyncPattern

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.

While this is good advice, it's not an answer. It's certainly a legitimate possibility that he needs to run it synchronously.
–
Adam RobinsonApr 12 '12 at 13:31

@AdamRobinson: there could no be a right answer on this. There could be a most suitable for OP answer. Blocking main thread is not good, if you need this, means that somethig wrong in design. If you don't want change design, have not time, can not do that for 1000 reasons you have 2 options: 1) Change library code (if it's possible, there is no meaning of asking a question, just chnage it in a way that it runs on single thread) 2) Do not use that library. Second is not asnwer definitely, so I choose just a suggession, it's up to the OP decide what is right for him.
–
TigranApr 12 '12 at 13:37

1

Certainly there are answers; just see mine and several others that actually address the question with different approaches. Not all code can be async. Does forcing synchronous execution mean that there's a possibility of bad design? Sure. Is it a certainty? No.
–
Adam RobinsonApr 12 '12 at 13:39

I know about that trend, I like it , but this application wouldn't benefit much from being asynchronous, while the development process becomes much harder. There's about 100 of different async calls in the library, and a lot of the could be executed only when another call is complete. Performing all the logics about switching which method to execute after one is completed in the eventhandler is not very easy while developing, and I guess would be extremly hard to support.
–
Georgy SmirnovApr 12 '12 at 13:51

@GeorgySmirnov: if you're using .NET4.0> so can use Tasks, you can use Task.ContinueWith clear notification code-design , which is the same form the behavioral point of view, but with much more accurate coding style.
–
TigranApr 12 '12 at 13:52

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.

public class SomeClass : BaseClass
{
public void ExecuteSomethingAndWaitTillDone()
{
// Set up the handler to signal when we're done
service.OnBeginSomethingCompleted += OnCompleted;
// Invoke the asynchronous method.
service.BeginSomething(...);
// Now wait until the event occurs
lock (_synchRoot)
{
// This waits until Monitor.Pulse is called
Monitor.Wait(_synchRoot);
}
}
// This handler is called when BeginSomething completes
private void OnCompleted(object source, ...)
{
// Signal to the original thread that it can continue
lock (_synchRoot)
{
// This lets execution continue on the original thread
Monitor.Pulse(_synchRoot);
}
}
private readonly Object _synchRoot = new Object();
}