如何等待BackgroundWorker完成运行另一个BackgroundWorker(C#)?

时间:2017-01-17 22:33:51

标签: c# backgroundworker autoresetevent waitone

首先,我还是初学者,所以如果你有耐心,我会很感激:)

我今天一直在为此苦苦挣扎。

问题是,我想要经营三个不同的背景工作者。但是我想等到一个人完成下一个的运行,依此类推。

每个背景工作者都需要时间来完成。长话短说,问题是,我使用WaitOne(),所以每当前一个背景工作者告诉我它完成后,我就可以开始运行新的,但是UI线程一直在冻结,直到三个后台工作者完成

我正在设置一个不同的AutoResetEvent,它负责整个等待和运行的事情。

以下是代码:

AutoResetEvent _resetRIEvent = new AutoResetEvent(false);
AutoResetEvent _resetHEvent = new AutoResetEvent(false);
AutoResetEvent _resetSEvent = new AutoResetEvent(false);

await Task.Run(() => bgwTestResInd.RunWorkerAsync());
_resetRIEvent.WaitOne();

await Task.Run(() => bgwTestHipot.RunWorkerAsync());
_resetHEvent.WaitOne();

await Task.Run(() => bgwTestSurge.RunWorkerAsync());
_resetSEvent.WaitOne();

MessageBox.Show("Im done for real.");

此外,是否可以这样做?

private void bgwTestResInd_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _resetRIEvent.Set();
}


private void bgwTestHipot_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _resetHEvent.Set();
}


private void bgwTestSurge_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _resetSEvent.Set();
}

2 个答案:

答案 0 :(得分:5)

不是创建后台工作人员,然后使用人工混合的任务和同步原语来在不同时间启动工作人员,而是从头到尾使用TPL完成整个工作:

await Task.Run(() => TheWorkThatTheFirstBGWWasDoing());
await Task.Run(() => TheWorkThatTheSecondBGWWasDoing());
await Task.Run(() => TheWorkThatTheThirdBGWWasDoing());

或者,如果所有操作都是CPU绑定工作,您只需使用一次Task.Run调用:

await Task.Run(() =>
{
    TheWorkThatTheFirstBGWWasDoing());
    TheWorkThatTheSecondBGWWasDoing());
    TheWorkThatTheThirdBGWWasDoing());
});

完成。

如果你真的必须使用后台工作者(没有充分理由,但无论如何),那么你需要做的就是在已完成的处理程序中调用RunWorkerAsync它需要等待的BGW,或者更好的是,只有一个BGW完成第一个工作,然后完成第二个工作需要做的工作,然后完成第三个需要的工作要做。

答案 1 :(得分:-1)

如果您仍想坚持您的计划,那么这里有代码

class Program
{

    static void Main(string[] args)
    {

        var test=new Test();
        test.Run();
        Console.ReadKey();
    }

    private class Test
    {
        AutoResetEvent _resetRIEvent = new AutoResetEvent(false);
        AutoResetEvent _resetHEvent = new AutoResetEvent(false);
        AutoResetEvent _resetSEvent = new AutoResetEvent(false);

        private BackgroundWorker bgwTestResInd = new BackgroundWorker();
        private BackgroundWorker bgwTestHipot=new BackgroundWorker();
        private BackgroundWorker bgwTestSurge=new BackgroundWorker();
        public async void Run()
        {
            bgwTestResInd.DoWork += BgwTestResInd_DoWork;
            bgwTestHipot.DoWork += BgwTestHipot_DoWork;
            bgwTestSurge.DoWork += BgwTestSurge_DoWork;

            await Task.Run(() => bgwTestResInd.RunWorkerAsync());
            _resetRIEvent.WaitOne();


            await Task.Run(() => bgwTestHipot.RunWorkerAsync());
            _resetHEvent.WaitOne();

            await Task.Run(() => bgwTestSurge.RunWorkerAsync());
            _resetSEvent.WaitOne();

            Console.Write("Done");
        }

        private void BgwTestHipot_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.WriteLine("BgwTestHipot done..");
            _resetHEvent.Set();
        }

        private void BgwTestSurge_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.WriteLine("BgwTestSurge done..");
            _resetSEvent.Set();
        }

        private void BgwTestResInd_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.WriteLine("BgwTestResInd done..");
            _resetRIEvent.Set();
        }
    }
}

只需将代码添加到DoWork方法中,它们将按照重置AutoResetEvents的顺序运行