C# backgroundworker RunworkerCompleted 与异步等待

标签 c# asynchronous async-await backgroundworker

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

#

我知道有很多关于 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/

相关文章:

c# - 如何进行多用户事件驱动的屏幕更新?

java - 设计通用的可取消异步操作接口(interface)

c# - ObservableCollection 项的异步更新

javascript - js等待 promise 调用自身

c# - 如何使多个 API 调用更快?

c# - 从任务继续写入 ASP.NET 响应输出流

c# - 在 Windows 8 应用程序中从 c# 代码更改资源颜色

c# - 文件读取问题 C++/C#

python - 用于异步周期性任务的 Django channel

javascript - 带有异步和等待 react native 的箭头功能