等待这些BackgroundWorker中的任何一个完成

时间:2010-02-02 01:39:38

标签: c# .net multithreading backgroundworker

应该使用服务下载FORM(某些UI)的序列。 目前,此下载位于BackgroundWorker线程中。 现在,由于性能很慢......我们决定将FORMS分类为2,并在现有Thread的基础上使用另一个BackgroundWorker并行开始下载。

现在,方案是这个BackgroundWorker应该等待其他任何一个完成。 那么,如何实现它。

我尝试使用AutoResetEvent。但是,我无法做到这一点。

感谢任何帮助。

5 个答案:

答案 0 :(得分:2)

我不认为这个场景确实是BackgroundWorker应该等待另一个场景。你真正想要的是在它们完成之后(并且仅在它们之后)发出一些UI事件。这是一个微妙但重要的区别;第二个版本更容易编码。

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
    }
}

请注意,那些object引用应该是强类型的,我只使用object,因为我不知道你要下载什么。

这真的是你所需要的; RunWorkerCompleted事件在前台线程中运行,因此您实际上不需要担心同步或竞争条件。不需要lock语句,AutoResetEvent等。只需使用两个成员变量来保存结果,或者如果两者的结果实际上可以是null,则使用两个布尔标志。

答案 1 :(得分:1)

您应该可以使用两个AutoResetEvent和WaitAll函数来等待两者完成。在相应的Set事件中调用AutoResetEvent对象上的OnRunWorkerCompleted函数。

答案 2 :(得分:1)

Jeffrey Richter是多线程的大师,他编写了一个名为Power Threading Library的神奇库,可以完成异步下载n个文件并在完成(或者一个或多个)之后继续执行的任务,真的简单。

花一点时间观看视频,了解它,你不会后悔。使用强大的线程库(免费并且还具有Silverlight和Compact Framework版本)也使您的代码更易于阅读,这在执行任何异步操作时都是一个很大的优势。

祝你好运, 标记

答案 3 :(得分:0)

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
}

答案 4 :(得分:0)

只需使用2个BackgroundWorker对象,并让每个对象在完成时提醒用户界面。这样你就可以显示一个微调器,进度条,UI上的任何内容,并在下载结果从线程返回时更新它。您还将避免任何线程死锁等风险。

顺便说一句,我们都清楚了,你绝不应该从UI线程调用一个阻塞函数,比如WaitAll。它会导致用户界面完全锁定,这会让你的用户想知道WTF正在发生:)