繁体   English   中英

C#backgroundworker RunworkerCompleted vs async await

[英]C# backgroundworker RunworkerCompleted vs async await

更新了答案:等待完成许多不同任务的真正方式需要异步等待而不是后台工作者。

我知道有很多关于背景工作者的讨论,但我一直在搜索,找不到答案。

这是我的代码示例(基本逻辑,实际代码要长得多),我想知道是否有办法解决这个问题:

void MCIATS1Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //do something here
    }

    void MCIATS1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("hello world");
        _MCIATS1WorkerResetEvent.Set();
    }

DoWork和runworker完成了

 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正在保持循环。
这是我的问题,

当工作人员实际完成工作时,为什么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线程开始处理消息循环中的新消息之前,事件无法运行。 但是,您阻止了UI线程通过_MCIATS1WorkerResetEvent.WaitOne();返回到消息循环_MCIATS1WorkerResetEvent.WaitOne(); 呼叫。

所以归结为_MCIATS1WorkerResetEvent.Set(); 等待MCIATS1_RunWorkerCompleted触发停止阻塞, MCIATS1_RunWorkerCompleted正在等待_MCIATS1WorkerResetEvent.Set(); 停止阻止UI线程,以便处理它的消息。

在事情完成之前,两件事都在等待对方完成,你有一个经典的死锁。

没有必要为一个for循环对于这个问题发生,同样的问题就会有或没有跳出循环发生,实际上循环永远不会获取运行它的第2个itteration,因为它会在第一时间僵持通过它确实是这样无论有什么循环都没关系。

根据您的MCIATS1Worker_DoWork方法所做的工作,您可以考虑使用async-await方法,这会使代码更加清晰。

private async Task MCIATS1WorkerDoWorkAsync()
{        
    await Task.Delay(1000) // do something asynchronously for 1 second
}

private async void MainWindow_Load(object sender, EventArgs e)
{
     for (int i = 1; i <= 10; i++)
     {
        //some code
        await MCIATS1WorkerDoWorkAsync();
        MessageBox.Show("hello world");
     }       
}

消息框每1秒显示10次。 只有在MCIATS1WorkerDoWorkAsync方法成功完成后, await关键字才会继续循环。

使用async-await您的表单将保持响应,如果DoWork方法执行某些IO操作,那么您将不会启动另一个线程(如BackgroundWorker那样)并且整个执行将在一个线程上发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM