Multithreading: adding cancelation to the initial event based pattern implementation

Today we’re going to improve the code we’ve started writing yesterday: we’re adding canceling support. As you might recall, in our last post we’ve built a simple class which supports a single asynchronous operation at a time. Since we only support one asynchronous operation at a time and we can only start one asynchronous operation from our class, then we only need to add a parameterless CancelAsync method.

Here’s how you might implement the CancelAsync method:

public void CancelAsync() {
    if (!_isRunning) {
       return;
    }
    _cancelOperation = true;
}

As you can see, we need to add a _cancel operation field which is used for notifying the helper method that runs in asynchronous mode that it should stop. This means that we need to change our asynchronous method slightly so that it checks that value in the for cycle and passes that value for the PrimeNumberVerificationCompletedEventArgs instance passed to whoever consumes the PrimeNumberCompleted event. Since I’ve cheated a little bit in the previous post, we’ve already got the hooking points for flowing the needed information. This means that changes are mostly concentrated on the IsPrimeAsync method:

public void IsPrimeAsync(Int32 number) {
  if (_isRunning) {
      throw new InvalidOperationException();
  }
  _isRunning = true;
  _currentOperation = AsyncOperationManager.CreateOperation(null);
  ThreadPool.QueueUserWorkItem(state =>
                  {
                      var numberToCheck = (Int32)number;
                      var isPrime = false;
                      Exception throwException = null;
                      try {
                          if (number > 2) {
                              isPrime = true;
                              var half = number / 2;
                              for (var i = 2; i < half && !_cancelOperation; i++) {
                                  if (number % i == 0) {
                                      isPrime = false;
                                      break;
                                  }
                              }                               
                          }
                      }
                      catch (Exception ex) {
                          throwException = ex;
                      }
                      finally {
                          NotifyEndOfOperation(numberToCheck,
                                               isPrime,
                                               _cancelOperation,
                                               throwException);
                      }

                  }, number);
}

There’s still one thing missing: we need to clean up the _cancelOperation flag when that asynchronous operation ends. This can be done from within the anonymous method we’re using inside the NotifyEndOfOperation method:

private void NotifyEndOfOperation( Int32 numberToTest,
  Boolean isPrime,
  Boolean cancelled,
  Exception thrownException ){
      var evt = new PrimeNumberVerificationCompletedEventArgs(
                  numberToTest,
                  isPrime,
                  thrownException,
                  cancelled,
                  null);
      _currentOperation.PostOperationCompleted(
          state => {
                      _isRunning = false;
                      _cancelOperation = false;
                      OnPrimeNumberCompleted((PrimeNumberVerificationCompletedEventArgs)state);
                   },
                  evt);
}

And that’s it. As you can see, supporting cancelation is not really that hard. We’ll keep improving this sample and on the next post we’ll see how we can improve our code so that it supports multiple asynchronous operations. Keep tuned.

Advertisements

~ by Luis Abreu on June 18, 2009.

One Response to “Multithreading: adding cancelation to the initial event based pattern implementation”

  1. WLz2kR Perfect work!

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: