.NET Framework Bookmark and Share   
 index > .NET Base Class Library > Help transmitting files asynchronously
 

Help transmitting files asynchronously

I'm having a bit of trouble structuring a class library for uploading files (via HTTP/FTP)and asynchronously reporting their progress. My first pass at code looks something like this:

WebClient wc = new WebClient();
// setup credentials, etc
...
// install callbacks
wc.UploadProgressChanged += new  UploadProgressChangedEventHandler(myProgressChanged);
wc.UploadFileCompleted += new UploadFileCompletedEventHandler(myFileCompleted);

foreach ( file to send )
{
  wait = new System.Threading.AutoResetEvent(false);
  // send file, block until done.
  wc.UploadFileAsync(URI, null, {file name}, wait);
  wait.WaitOne();
}
This is running on the main UI thread. The Progress callback updates a window of status information. The Completed callback sets the "wait" event object, to release the block following the asynch send.

The problem is that the entire code blocks on the WaitOne call -- the Progress() and Completed() callbacks never get called (even though the file is succesfully sent ok). I would have that these callbacks would be issued on the thread processing the async send, but apparently this isn't so. (even though MS's documentation for the event: http://msdn.microsoft.com/en-us/library/system.net.uploadfilecompletedeventhandler.aspxuses just such a model).

If I remove the WaitOne call, everything works fine -- for one single file. But without synchronizing, multiple sends are dispatched simultaneously. This could be worked around by unrolling the foreach loop into the Completed() handler to simulate synchronous operation, but that seems a bit messy. Is there a better solution other than spawning this all off onto its own thread?

Thanks in advance,


masher
masher2
The WaitOne doesn't deadlock -

THe problem is, your callback needs to marshall back onto the UI thread, but the WaitOne is causing your UI thread to be blocked. There isn't a (good) way to have a progress bar on your UI updating if you're blocking...

You are right, though- pushing this entire process onto a background thread would be another option, if you prefer it to unrolling the loop. I'd, personally, just unroll the loop - that seems simpler to me, but that's just my opinion.
Reed Copsey, Jr.
The problem is that your main, UI thread is waiting on the WaitOne, so the progress events can never fire.

Instead of waiting, can you just setup your collectino of files to send (Queue<string> files, or similar?), and have your UploadFileCompleted start the processing if the next item in the queue?

The nice thing about doing it that way is that you never have to block on the UI thread - you can just go about uploading, report your events, and start your next file as soon as the last one finished.
Reed Copsey, Jr.

> "can you just...have your UploadFileCompleted start the processing if the next item in the queue?"

I can...that's what I meant by "unrolling the loop in the Completed() callback". But that somehow just doesn't feel very elegant to me somehow, especially when MS has sample code saying that a Wait event should work. The callbacks really should be being fired by the (separate) transfer thread, so the WaitOne() call shouldn't deadlock.


masher
masher2
The WaitOne doesn't deadlock -

THe problem is, your callback needs to marshall back onto the UI thread, but the WaitOne is causing your UI thread to be blocked. There isn't a (good) way to have a progress bar on your UI updating if you're blocking...

You are right, though- pushing this entire process onto a background thread would be another option, if you prefer it to unrolling the loop. I'd, personally, just unroll the loop - that seems simpler to me, but that's just my opinion.
Reed Copsey, Jr.

You can use google to search for other answers

Custom Search

More Threads

• Collection was modified; enumeration operation may not execute
• body tag runat=server doesn't work on master page
• Window size problem
• Emit a Call to an external function --> TargetInvocationException
• SqlParameter.IsNullable with DeriveParameters
• Hash Table
• ApplicationSettingsBase question
• Overwrite infos in a file
• How to migrate from CMAB to the System.Configuration in .NET 2.0?
• Why Can't I compress a serialized object?