Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use AsyncOperation and AsyncOperationManager

I've spent many many hours tonight reading up on implementing the event-based asynchronous pattern

Unfortunately, I haven't been able to find any articles at all on witting a class that only supports one Async invocation.

Every example I've seen assumes that a method call will be called more than once and thus, should have a userState object passed into the MethodNameAsync

You'll see that MS makes mention of this in the third bullet point on this article http://msdn.microsoft.com/en-us/library/ms228974(VS.80).aspx under the "Simultaneously Executing Operations" heading.

But I'm confused. Should I be using AsyncOperation and AsyncOperationManager classes to have asynchronous functionality where a method can only be called by one thread at a time?

A link would also be nice :)

Thanks

like image 618
Razor Avatar asked Dec 10 '22 20:12

Razor


1 Answers

First of all, we need to say what synchronization context is.
Synchronization context is a class, which decides on which thread operations should be executed.
Main synchronization context classes - SynchronizationContext and WindowsFormsSynchronizationContext - are just simple classes which can delegate the operations to other threads.
SynchronizationContext.Post() method just delegates an operation to some thread from a thread pool (using ThreadPool.QueueUserWorkItem(...) method internally).
SynchronizationContext.Send() method just executes the delegate in the same thread.
Most frequent use of WindowsFormsSynchronizationContext is the following: WindowsFormsSynchronizationContext is internally set for the main GUI thread when you create main form of your application. Later this synchronization context is used to execute delegates on the same main GUI thread.

So, I will conclude, synchronization context is a simple class which decides on which thread a delegate will be executed.

Now, let's return to the AsyncOperationManager class.
You may use AsyncOperationManager class when you need to execute operation on some synchronization context. The synchronization cotnext on which the operation will be executed can be either:

1) The same synchronization context in which you call AsyncOperationManager.CreateOperation() method, if the thread has a SynchronizationContext defined.
or
2) New syncronization context (represented by a new instance of the base SynchronizationContext class), if current thread doesn't have a synchronization context defined yet. The instance of base SynchronizationContext class, as I already said earlier, will execute delegates on some thread from a thread pool.

Basically, AsyncOperationManager is just a simple helper class which uses AsyncOperation and SynchronizationContext classes internally.

Now, about the usage scenarios.
For example, in your main GUI thread you create a class which provides asynchronous operations using event based async pattern (i.e. it provides events which report progress).
You want your event handlers to be executed in the same GUI thread, so you will be able to work with your GUI controls from the event handlers.
In this case in the OperationAsync method you create an AsyncOperation object and store it for later use:

public void OperationAsync(object arg1, object arg2, ...)
{
  _asyncOperation = AsyncOperationManager.CreateOperation(null);
  /* _asyncOperation object now captured current synchronization 
     context, which is WindowsFormsSynchronizationContext if you 
     run this method from GUI thread. */
  ...
}

And when operation completes you raise OperationCompleted event using AsyncOperation.Post() method. If you run AsyncOperationManager.CreateOperation() method from the GUI thread of your application, the event handlers will be executed on the same thread - i.e. on your main GUI thread:

private void OnOperationCompleted(AsyncCompletedEventArgs e)
{
  EventHandler<AsyncCompletedEventArgs> handler = OperationCompleted;
  if(handler != null)
  {
    _asyncOperation.Post(
      delegate
      {
        handler(this, e);
      },
      null);

    _asyncOperation.OperationCompleted();
  }
  ....
}
like image 169
nightcoder Avatar answered Dec 28 '22 00:12

nightcoder