更新了答案: 等待多个不同任务完成的真正方法需要异步等待而不是后台工作程序。
#我知道有很多关于 backgroundworker 的讨论,但我一直在搜索,但找不到答案。
这是我的代码示例(基本逻辑,实际代码要长得多),我想知道是否有办法解决这个问题:
BackgroundWorker MCIATS1Worker = new BackgroundWorker();
private AutoResetEvent _MCIATS1WorkerResetEvent = new AutoResetEvent(false);
public MainWindow()
{
InitializeComponent();
MCIATS1Worker = new BackgroundWorker();
MCIATS1Worker.DoWork += new DoWorkEventHandler(MCIATS1Worker_DoWork);
MCIATS1Worker.WorkerReportsProgress = true;
MCIATS1Worker.WorkerSupportsCancellation = true;
MCIATS1Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MCIATS1_RunWorkerCompleted);
for (int i = 1; i <= 10; i++)
{
//some code
MCIATS1Worker.RunWorkerAsync();
_MCIATS1WorkerResetEvent.WaitOne();
}
}
DoWork 和 runworkercompleted
void MCIATS1Worker_DoWork(object sender, DoWorkEventArgs e)
{
//do something here
}
void MCIATS1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("hello world");
_MCIATS1WorkerResetEvent.Set();
}
由于某些原因,MCIATS1_RunWorkerCompleted 在循环完成之前不会被触发。显然 WaitOne 正在控制循环。
这是我的问题,
为什么 Worker 真正完成工作时,RunWorkerCompleted 不会触发 RunWorkerCompleted?
谢谢。
###更新的解决方案这是正确的做法。
private async void WhateverFunction()
{
await Task.WhenAll(MCIATS1WorkerDoWorkAsync(param),...other tasks);
}
private Task MCIATS1WorkerDoWorkAsync(bkgWorkParameter param)
{
return Task.Run(() =>
{
//Do whatever
});
}
最佳答案
发生这种情况是因为当您使用 BackgroundWorker
时,RunWorkerCompleted
事件被发布到调用 RunWorkerAsync< 的线程的
.SynchronizationContext
/
因为您在 UI 线程上调用了 RunWorkerAsync
,所以在 UI 线程开始处理消息循环中的新消息之前,事件无法运行。但是,您通过 _MCIATS1WorkerResetEvent.WaitOne();
调用阻止了 UI 线程返回消息循环。
所以它归结为 _MCIATS1WorkerResetEvent.Set();
正在等待 MCIATS1_RunWorkerCompleted
触发以停止阻塞,而 MCIATS1_RunWorkerCompleted
正在等待_MCIATS1WorkerResetEvent.Set();
停止阻塞 UI 线程,以便处理消息。
两件事情都在等待对方完成,然后自己完成,这就是典型的死锁。
这个问题不需要 for
循环,无论有没有循环,同样的问题都会发生,事实上,循环永远不会运行它的第二次迭代,因为它会在第一次通过时就陷入了僵局,所以有一个循环根本无关紧要。
关于C# backgroundworker RunworkerCompleted 与异步等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43688981/