2010-02-02 77 views
3

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

现在,场景是这个BackgroundWorker中的任何一个都应该等待其他人完成。 那么,如何实现它。

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

任何帮助表示赞赏。

回答

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)。

+0

这是正确的答案。 +1 – 2012-02-29 05:24:31

1

Jeffrey Richter是多重线程领域的大师,他编写了一个叫做Power Threading Library的令人惊叹的库,它可以完成任务,例如异步下载n个文件并在所有完成(或一个或多个)完成后继续执行,非常简单。

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

祝你好运, 马克

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

只需使用2个BackgroundWorker的对象,并有每一个警报的UI完成时。这样,您可以在UI上显示微调器,进度条和任何内容,并在线程下载结果返回时进行更新。你也将避免任何线程死锁的风险等。

顺便说一下,就这样我们都清楚,你永远不应该从UI线程调用诸如WaitAll的阻塞函数。它会导致用户界面完全锁定,这会让你的用户不知道跆拳道是怎么回事:)