William さんのプロフィール.Net Zoneブログリスト ツール ヘルプ
9月7日

Wait for async completion using two locks instead of an event.

 

Sometimes you need to wait (or block) for an async method to complete.  This could be
because your creating a sync method wrapper for your async method or for other reasons.
Sometimes you just want a blocking method to make is easy and your program does not
really need to async behavior.  What ever the reason, here is method to block your calling
thread until the async event completes.  You could also create and wait on an Autoreset event
each time, but that is very slow in comparison to below (even two locks is 100X factors faster
then using Autoreset events.

The key is to use two locks.  The first is just an exclusive lock to keep other callers blocked.  The second
lock does the work.  We use Monitor.Wait to wait for the async event to complete and Monitor.Pulse
to free the thread.  I guess you could call this a User mode reset event.  You could even wrap it up in a class to codify it.  Maybe I will do that in a future post.

            object syncRoot = new object();
            object exclusiveLock = new object();
            //...
 
            lock (exclusiveLock)
            lock (syncRoot)
            {
                // Kick off async here and pulse syncRoot to free thread when complete.
                new Thread(
                    delegate()
                    {
                        Console.WriteLine("Inside async routine.");
                        Thread.Sleep(1000);
                        lock (syncRoot) // Need to own lock before pulse.
                        {
                            Monitor.Pulse(syncRoot);    // Pulse Waiting thread.
                        }
                        Console.WriteLine("Pulsed syncroot.");
                    }).Start();
 
                // Wait for async callback to complete.
                Monitor.Wait(syncRoot);
            } // Exit both locks.