Jun 24

Multithreading: AsyncOperationManager and AsyncOperation helpers

Posted in C# Multithreading      Comments Off on Multithreading: AsyncOperationManager and AsyncOperation helpers

In the last posts, we’ve taken a look at how synchronization contexts help marshal work across threads. Today we’re going to talk about two classes (which we’ve already met in the past when we implemented the EAP) that abstract even further the use of synchronization contexts: I’m talking about the AsyncOperationManager and AsyncOperation classes. Let’s start with the AsyncOperationManager class.

The AsyncOperationManager is a simple helper class with very few lines of code in it, as you can see from the next snippet:

public static class AsyncOperationManager {
  public static AsyncOperation CreateOperation(
object userSuppliedState); public static SynchronizationContext
SynchronizationContext { get; set; } }

As you can see, this is a static class with only two members. The SynchronizationContext property lets you access or set the current SynchronizationContext. The biggest advantage it offers when compared with accessing the synchronization context through the SynchronizationContext.Current property (which we’ve used in the previous post) is that you’ll always get a valid context (notice the comment in the previous post’s sample).

The CreateOperation method is the only way you have to create an instance of the AsyncOperation type. Each AsyncOperation instance can only track one asynchronous operation. The AsyncOperation type exposes the following members:

public sealed class AsyncOperation {
  public void OperationCompleted();
  public void Post(SendOrPostCallback d, object arg);
  public void PostOperationCompleted(
SendOrPostCallback d, object arg); public SynchronizationContext
SynchronizationContext { get; } public object UserSuppliedState { get; } }

A couple of observations about the previous methods exposed by the AsyncOperation type:

  • you can access the current synchronization context through the SynchronizationContext property;
  • the UserSuppliedState property lets you access the optional state parameter that you’ve passed through the userSuppliedState parameter (AsyncOperationManager.CreateOperation method);
  • you’re supposed to use the Post operation to marshal a notification back to the “main” thread;
  • you’re supposed to signal the end of the asynchronous operation by calling the PostOperationCompleted method.

As you can see, the AsyncOperation will always perform the operation in asynchronous fashion (ie, it will always invoke the Post method of the internal SynchronizationContext). The main difference between Post and PostOperationCompleted resides in an internal flag that is set by the 2nd method. After this flag is set, all invocations of the Post/PostOperationCompleted methods end up throwing exceptions.

By now, I’m thinking that you’ve got enough information for understanding the use of these types when we saw how to implement the EAP pattern in a previous post, so I’m not going to waste your time repeating what has been said before.

And that’s all. With this post, I guess that there’s only one thing to talk about: the BackgroundWorker class. We’ll leave that topic for the next post. Keep tuned for more.