Multithreading: waiting on the APM’s WaitHandle

Today, we’re going to keep looking at the available options waiting for the conclusion of an asynchronous task started through the APM model. In this post we’re going to see how we can use the WaitHandle which we can get through the IAsyncResult’s AsyncWaitHandle property.

After getting a valid reference to it, you can do what you normally do with handles: make the thread wait until it gets signaled. You might say: “dude, what’s the difference between this approach and the previous one?” And I say: “dude, you have more control with this approach”. “How”, you ask…glad you did that :,,)

In the previous option, you get blocked, waiting until the operation completes. On the other hand, if you a get a reference to the WaitHandle, then you can block and specify a *timeout*! This means that you can specify a maximum amount of time for the execution of the task or you could use a cycle with a small timeout for giving feedback to the user.

Besides the timeout option, it’s also important to keep in mind that, once you have a reference to the WaitHandle, you have the option to wait for several handles (by calling the WaitAll or WaitAny methods). To show you how we can use this approach, lets see some code. We’ll migrate the latest sample to use this approach:

var request = WebRequest.Create("http://msmvps.com/blogs/luisabreu");
var result = request.BeginGetResponse(null, null);
Console.WriteLine("async request fired at {0}", DateTime.Now);
while (!result.AsyncWaitHandle.WaitOne(500, false)) {
    //give feedback
    Console.WriteLine("Operation executing: {0}", DateTime.Now);
}
WebResponse response;
try {
    response = request.EndGetResponse(result);
}
catch (WebException ex) {
   //same as before
}

As you can see, the code is similar to the one we had before: however, in this case we’re accessing the WaitHandle and waiting on it for 500 ms. When the method returns false, we give feedback to the user. When it returns true, we end up calling EndGetResponse for getting the response.

Before ending up, there’s still time to remind you that you should always call the EndXXX method for cleaning up the resources used. It’s important to keep this in mind! For instance, if in the previous sample you decide to wait only for 500ms and then discard the results (if they aren’t computed in that time), you can’t simply keep doing what you want without calling the EndXXX method…in these cases, the best option is to use a thread from the pool to do that:

if (!result.AsyncWaitHandle.WaitOne(500, false)) {
ThreadPool.UnsafeQueueUserWorkItem(
           (state) => {
                try {
                    request.EndGetResponse(result);
                }
                catch (WebException ex) {
                    //log error…
                }
            },
            null);
}

As you can see, we don’t care about propagating the context and that’s why we’re using the UnsafeQueueUserWorkItem method.

And that’s it for today. There are still two other options for waiting on the APM, but we’ll leave them for future posts. Keep tuned for more on asynchronous multithreading.

Advertisements

~ by Luis Abreu on June 9, 2009.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: