有一个FORM(某些UI)应该使用服务下载的序列。 目前,此下载位于BackgroundWorker主题中。 现在,由于性能很慢...我们决定将FORMS分类为2,并在现有的Thread之上使用另一个BackgroundWorker并行开始下载。等待这些BackgroundWorker中的任一个完成
现在,场景是这个BackgroundWorker中的任何一个都应该等待其他人完成。 那么,如何实现它。
我试着用AutoResetEvent。但是,我无法做到这一点。
任何帮助表示赞赏。
有一个FORM(某些UI)应该使用服务下载的序列。 目前,此下载位于BackgroundWorker主题中。 现在,由于性能很慢...我们决定将FORMS分类为2,并在现有的Thread之上使用另一个BackgroundWorker并行开始下载。等待这些BackgroundWorker中的任一个完成
现在,场景是这个BackgroundWorker中的任何一个都应该等待其他人完成。 那么,如何实现它。
我试着用AutoResetEvent。但是,我无法做到这一点。
任何帮助表示赞赏。
我不认为这种情况真的是那个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
)。
您应该可以使用两个AutoResetEvent和WaitAll函数等待两个完成。在相应的OnRunWorkerCompleted事件中的AutoResetEvent对象上调用Set函数。
Jeffrey Richter是多重线程领域的大师,他编写了一个叫做Power Threading Library的令人惊叹的库,它可以完成任务,例如异步下载n个文件并在所有完成(或一个或多个)完成后继续执行,非常简单。
花点时间观看视频,了解它,你不会后悔。使用功能线程库(也就是免费,并且还具有Silverlight和Compact Framework版本)也使您的代码更易于阅读,这在执行任何异步内容时是一大优势。
祝你好运, 马克
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
}
只需使用2个BackgroundWorker的对象,并有每一个警报的UI完成时。这样,您可以在UI上显示微调器,进度条和任何内容,并在线程下载结果返回时进行更新。你也将避免任何线程死锁的风险等。
顺便说一下,就这样我们都清楚,你永远不应该从UI线程调用诸如WaitAll的阻塞函数。它会导致用户界面完全锁定,这会让你的用户不知道跆拳道是怎么回事:)
这是正确的答案。 +1 – 2012-02-29 05:24:31