2

I have multiple asynchronous methods that I need to call and wait for them all to finish. The asynchronous methods all have callback parameters that execute when the asynchronous processing has finished. So I'm thinking that I need to put some signalling device in each callback and then wait for all the signals to come before continuing.

After doing some searching I'm thinking I could use a an array of AutoResetEvents and then call WaitHandle.WaitAll to wait for them. Something like:

WaitHandle[] waitHandles = new WaitHandle[] { new AutoResetEvent(false), new AutoResetEvent(false) }; DoWorkA((callback) => { waitHandles[0].Set(); }); DoWorkB((callback) => { waitHandles[1].Set(); }); // wait for DoWorkA and DoWorkB to finish WaitHandles.WaitAll(waitHandles); // continue with the processing 

I'd like to know if this is a good way to do it, or if there is a better/simpler method. I need an solution for .Net 2.0, but I'd also be interested to know what other solutions would be available with a later version of .Net.

EDIT: After trying this code I found it doesn't work. The UI thread stops at WaitHandles.WaitAll(waitHandles) and the callbacks never run...

Inside the DoWork methods there is code being run asnychronously on a background thread, and then from that background thread I attempt to run the callback through BeginInvoke called on a control from the UI thread. However, the callback never gets executed on the UI thread. Any ideas what I'm doing wrong?

EDIT 2: I realized why it doesn't work - the thread calling WaitHandles.WaitAll(waitHandles) is the same thread that the callbacks are attempting to run on (the UI thread). So of course if the thread is waiting for the signal, the callbacks will never run on that same thread and so Set() will never be called. The WaitAll(waitHandles) and Set() should work, as long as they are not inteded to be run on the same thread. I think I need to fix it so that the callbacks run on a background thread while the UI thread waits. Please let me know if my thinking here is incorrect.

1 Answer 1

6

Yes using events is reasonable way to wait for multiple callback completion and for 2.0 it is probably the best you can do if you can't use external libraries.

You may rewrite code with one event and counting callback completion, but it may be more complicated (also allow unlimited number of callbacks at the same time). Or similar approach may be implemented via Semaphore.

If you can use 4.5+ than rewriting methods with async/await may be better option.

 // use "async Task(...)" as equivalent of "void DoWorkA(...)". async Task<int> DoWorkAAsync(int arg1) { var serviceResult = await service.CallAsync(arg1); return ParseServiceResult(serviceResult); } async Task<int> DoWorkBAsync() { ... await SomeAsync(1,2,3);... return someResult; } var tasks = new[] {DoWorkAAsync(42), DoWorkBAsync() }; await Task.WhenAll(tasks); var resultOfA = tasks[0].Result; 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the info on 4.5 (just for learning purposes). However, I'm not able to rewrite the methods I'm calling (DoWorkA, DoWorkB in the example), I have to call them as is so I need to work with their callbacks... As for using a semaphore, how would that work?
@JPProgrammer Semaphore - start at number of callback and wait, ReleaseSemaphore in each callback, as result original thread will continue when release called number_of_callbacks times. Async/await: check out stackoverflow.com/questions/15575579/… for way to reuse methods with callbacks in async/await world.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.