Framework Madness!

And other adventures C# and asp.net …

Async Async – Using BackgroundWorker and WebClient async upload together (Part 1)

with 4 comments

Updated 1/19/2009

The discussion on using BackgroundWorker here is good but I had to abandon the use of the WebClient class inside the upload object.

 

Doing async with the BackgroundWorker class (System.ComponentModel) is easy, but when I realized that async could also be done with the WebClient class (System.net) while the BackgroundWorker is executing I had to give it a try so that I could support cancelation. It works, but you have to follow the BackgroundWorker async pattern carefully.

In my case I created a Delivery class that has the responsibility of setting up the BackgroundWorker, staging ftp execution, and clean up. I have an Upload object that manages the async FTP upload separately . This Upload object  is created when Delivery.Execute is called and then passed along to the BackgroundWorker.DoWork event hander, named InitDelivery, for execution. Here’s the code for InitDelivery:

   1: private void InitDelivery(object sender, DoWorkEventArgs e)
   2: {
   3:    if (e.Argument as FTPUpload != null)
   4:    {
   5:        var Upload = e.Argument as FTPUpload;
   6:  
   7:        this.Upload = Upload;
   8:  
   9:        Upload.ExecuteAsync();
  10:  
  11:        //wait here for upload to complete
  12:        while (Upload.IsBusy)
  13:        {
  14:              Thread.Sleep(10);
  15:        }
  16:    }
  17:  
  18:  
  19:  
  20:    e.Result = e.Argument;
  21: }

Here is how it works:

1) The Upload object is retrieved from the e.Argument.

2) The Upload object is passed to a local field so that it’s internal async operation can be canceled if need be.

3) The method Upload.ExecuteAsync is called.

4) Next we wait for the ‘while(Upload.IsBusy)’ to compete. But you might ask why I am doing this if I am using an async in the Upload object?  Here are the reasons:

  • The BackgroundWorker is designed for managing long running, synchronous tasks so we need to mimic that pattern inside the BackgroundWorker.DoWork  event handler.
  • The Upload.IsBusy state is always set to false when the internal async operation finishes regardless of completion, cancelation, or exception.
  • I need to use state from the Upload object in the BackgroundWorker.RunWorkerCompleted event handler.

5) The Upload object is passed to e.Result and the event handler exits.

 

The BackgroundWorker.RunWorkerCompleted event is wired to DeliveryFinish. Here is the code:

   1: private void DeliveryFinish(object sender, RunWorkerCompletedEventArgs e)
   2: {
   3:    try
   4:    {
   5:  
   6:        //set the error
   7:        this.Error = e.Error;
   8:  
   9:        var Upload = e.Result as Upload;
  10:  
  11:        if (Upload != null)
  12:        {
  13:            if (this.Error == null && Upload.Error != null)
  14:            {
  15:                this.Error = Upload.Error;
  16:            }
  17:  
  18:             // perform logging and clean up here
  19:        }
  20:  
  21:        
  22:    }
  23:    finally
  24:    {
  25:        //set iscompleted
  26:        this.IsFinsihed = true;
  27:    }
  28:  }

 

Here is how it works:

1) The Delivery.Error property is set from e.Error and the Upload object is retrieved from e.Result.

2) If the Upload object has an error then it is forwarded to the Delivery.Error property.

3) Perform any logging and clean up as necessary.

4) The Try/Finally block ensures that Delivery.IsFinished is always set to true.

 

Update 2009-01-16

Looks like the ‘Upload.IsBusy’ thread really hammers the processor. To remove that I’ve added a Thread.Sleep call that really dampens things down, and it does keep the transfer working.

 

That’s it for Part 1. In Part 2 I’ll look at the Upload object and cover a few highlights. Here is the link:

https://leriksen71.wordpress.com/2009/01/19/async-only-using-the-background-worker-with-ftpwebrequest-part-2-sort-of/

Advertisements

Written by Lynn Eriksen

January 15, 2009 at 11:01 am

Posted in Uncategorized

Tagged with ,

4 Responses

Subscribe to comments with RSS.

  1. […] a comment » In the article Async Async – Using BackgroundWorker and WebClient async upload together (Part 1) I covered the use of the BackgroundWorker and planed to use the WebClient to upload files via […]

  2. Ummm. Can I ask WHY you need a BackgroundWorker when the WebClient async methods do proper background prcessing for you?

    All you’re doing is forcing the CPU to context switch vastly more than it needs to.

    Sean Hederman

    February 19, 2010 at 4:13 am

    • Sean, good question.
      In the project that I was working on I wanted to be able to run multiple uploads in parallel, so I decided to go with async. Then at some point in the project I discovered that one of the FTP servers I was sending to was receiving the file but not hanging up properly, and the Web Client was not reporting this properly as a Completed event or what ever event it was supposed to. So I had to ditch the WebClient and roll my own solution with FtpWebRequest.

      Lynn Eriksen

      February 19, 2010 at 10:40 am

  3. Can you give complete source code to make every thing very clear please.

    Mahesh Chavan

    September 16, 2013 at 5:11 am


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: