LA.NET [EN]

Jun 20

I know that I’ve said that the next post of the series would be on how to support several asynchronous tasks. However, I was reminded by a friend that I didn’t had any post on how to support the optional progress info feature. So, I decided to take a small detour today and we’ll see how we can modify our class so that it is able to report progress back to the user.

As we’ve seen, progress is exposed through an event named ProgressChanged, of type ProgressChangedEventHandler (notice that if you have several diferent asynchronous method, then you should name the event XXXProgressChanged, where XXX is the name of the asynchronous method).

Here’s the code we’re using to fire the event:

public event ProgressChangedEventHandler ProgressChanged;
protected void OnProgressChanged(ProgressChangedEventArgs evt){
   
if (ProgressChanged != null) {
        ProgressChanged(
this, evt);
    }
}

As you can see, this is standard stuff, ie, we’ve added the event and then an OnEventName method which is responsible for firing the event (btw, keep in mind that if the class you’re building isn’t sealed,then you should make the method virtual so that a derived class can use overrides as a way to “handle” the event ).

As you might guess by now,progress report must come from the method that does the work. In this case, we’re talking about an anonymous method that is passed to the ThreadPool.QueueUserWorkItem method. In this example, calculating the progress is easy and depends on the total number of elements used in the for loop:

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;
          var currentProgress = 0f;
          for (var i = 2; i < half && !_cancelOperation; i++) {
              if (number % i == 0) {
                  isPrime = false;
                  break;
              }
              currentProgress = ((float)i  / (float)half) * 100;
              _currentOperation.Post(
                      evtState => OnProgressChanged(
                             (ProgressChangedEventArgs)evtState ),
                      new ProgressChangedEventArgs(
(
Int32)currentProgress, null)); } } } catch (Exception ex) { throwException = ex; } finally { NotifyEndOfOperation(numberToCheck,
isPrime, _cancelOperation, throwException); } }, number); }

If you compare this code with the previous snippet, you’ll see that we added a currentProgress local variable for tracking the progress of the current operation and that we’re using our AsyncOperation instance (_currentOperation field) for marshalling the results and invoking the OnProgressChanged event from the “main thread” (where “main thread” is the thread that started the operation). And that’s it. From this point on, you can also get progress information by hooking up the ProgressChanged event:

work.ProgressChanged += (sender, e) => { //do something here with progress info};

And that’s it for today. On the next post, we’ll talk about the changes we need to make to the current code so that we can support several asynchronous executions of the IsPrimeAsync method. Keep tuned!

PS: I’ve followed Tuna’s twitter suggestion and I’ve used a plug-in for showing code in color. Do you guys prefer it this way?

1 comment so far

  1. Whilegas
    4:13 pm - 12-7-2009

    Defendant Response,soft construction means okay close provided sector do post god priority poor yard go conference possible press travel comment initiative rely ground invite maybe particular heart doubt useful version arm wing meanwhile name straight wash apparent hot conclusion associate winter ourselves work include build difference list this tape late concept young breath position emerge about hour pick league family intention serious shoot wide building gas the mark servant equally to eye touch reflect along write otherwise improve influence arrange suggest suddenly silence restaurant mother

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>