应该使用服务下载FORM(某些UI)的序列。 目前,此下载位于BackgroundWorker线程中。 现在,由于性能很慢......我们决定将FORMS分类为2,并在现有Thread的基础上使用另一个BackgroundWorker并行开始下载。
现在,方案是这个BackgroundWorker应该等待其他任何一个完成。 那么,如何实现它。
我尝试使用AutoResetEvent。但是,我无法做到这一点。
感谢任何帮助。
答案 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)
花一点时间观看视频,了解它,你不会后悔。使用强大的线程库(免费并且还具有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正在发生:)