views:

197

answers:

5

Hi...

There is a sequence for FORM(some UI) should get downloaded using service. Currently, this download is in a BackgroundWorker Thread. Now, since the performance is slow... We decided to categories the FORMS into 2 and start downloading parallely using another BackgroundWorker on top of the existing Thread.

Now, the scenario is the either of this BackgroundWorker should wait for other to complete. So, how to implement it.

I tried with AutoResetEvent. but, i could not achieve this.

Any help is appreciated.

Warm regards, Dinakaran.

A: 

You should be able to use two AutoResetEvent's and the WaitAll function to wait for both to complete. Call the Set function on the AutoResetEvent objects in the respective OnRunWorkerCompleted event.

SwDevMan81
+1  A: 

Jeffrey Richter is THE guru when it comes to multi threading and he's written an amazing library called Power Threading Library which makes doing tasks like downloading n files asynchronously and continuing after they are all completed (or one or some), really simple.

Take a little time out to watch the video, learn about it and you won't regret it. Using the power threading library (which is free and has a Silverlight and Compact Framework version also) also makes your code easier to read, which is a big advantage when doing any async stuff.

Good luck, Mark

wallismark
A: 
int completedCount = 0;

void threadProc1() { //your thread1 proc
//do something
....

completedCount++;
while (completedCount < 2) Thread.Sleep(10);
//now both threads are done
}

void threadProc2() { //your thread1 proc
//do something
....

completedCount++;
while (completedCount < 2) Thread.Sleep(10);
//now both threads are done
}
poiuyttr
A: 

Just use 2 BackgroundWorker objects, and have each one alert the UI when it completes. That way you can display a spinner, progress bar, whatever on the UI and update it as download results come back from the threads. You will also avoid any risks of thread deadlocking, etc.

By the way, just so we are all clear, you should NEVER call a blocking function such as WaitAll from the UI thread. It will cause the UI to completely lock up which will make you users wonder WTF is going on :)

Justin Ethier
A: 

I don't think that the scenario is really that one BackgroundWorker should wait for another. What you really want is to fire some UI event after (and only after) both of them complete. It's a subtle but important difference; the second version is a lot easier to code.

public class Form1 : Form
{
    private object download1Result;
    private object download2Result;

    private void BeginDownload()
    {
        // Next two lines are only necessary if this is called multiple times
        download1Result = null;
        download2Result = null;

        bwDownload1.RunWorkerAsync();
        bwDownload2.RunWorkerAsync();
    }

    private void bwDownload1_RunWorkerCompleted(object sender,
        RunWorkerCompletedEventArgs e)
    {
        download1Result = e.Result;
        if (download2Result != null)
            DisplayResults();
    }

    private void bwDownload2_RunWorkerCompleted(object sender,
        RunWorkerCompletedEventArgs e)
    {
        download2Result = e.Result;
        if (download1Result != null)
            DisplayResults();
    }

    private void DisplayResults()
    {
        // Do something with download1Result and download2Result
    }
}

Note that those object references should be strongly-typed, I just used object because I don't know what you're downloading.

This is really all you need; the RunWorkerCompleted event runs in the foreground thread so you actually don't need to worry about synchronization or race conditions in there. No need for lock statements, AutoResetEvent, etc. Just use two member variables to hold the results, or two boolean flags if the result of either can actually be null.

Aaronaught