C# 后台工作者 RunworkerCompleted 与异步等待

Hei*_*erg 5 c# asynchronous backgroundworker async-await

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

#

我知道有很多关于后台工作者的讨论,但我已经被四处搜索但找不到答案。

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

 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();
        }

    }
Run Code Online (Sandbox Code Playgroud)

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();
    }
Run Code Online (Sandbox Code Playgroud)

由于某些原因,在循环完成之前不会触发 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
        });
    }
Run Code Online (Sandbox Code Playgroud)

Fab*_*bio 3

根据你的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");
     }       
}
Run Code Online (Sandbox Code Playgroud)

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

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