我如何知道多个后台工作人员何时完成?

时间:2017-06-06 20:09:35

标签: c# multithreading backgroundworker

所以现在我有一个方法可以调用三次不同的方法。

List<BackgroundWorker> bgws = new List<BackgroundWorker>();
AutoResetEvent _workerCompleted = new AutoResetEvent(false);

void methodA () {
    methodB(); //bw1
    methodB(); //bw2
    methodB(); //bw3

    //wait for the background workers that were kicked off above to finish
    _workerCompleted.WaitOne();

    Console.Writeline("hey");
}

void methodB() {
    BackgroundWorker bw = new BackgroundWorker();
    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;
    bgws.Add(bw);

    bw.DoWork += (sender, DoWorkEventArgs) => { bwWork(sender, DoWorkEventArgs, info); };
    bw.ProgressChanged += (sender, ProgressChangedEventArgs) => { bwProgressChanged(sender, ProgressChangedEventArgs, info); };
    bw.RunWorkerCompleted += (sender, RunWorkerCompletedEventArgs) => { bwCompleted(sender, RunWorkerCompletedEventArgs, info); };

    bw.RunWorkerAsync();

}

bwWorkbwProgressChanged事件无关紧要。前者只是处理文件,后者正在更新进度条和标签。

private void bwCompleted(object senderr, 
System.ComponentModel.RunWorkerCompletedEventArgs e, SenderInfo info)
{
    BackgroundWorker bw = (BackgroundWorker)senderr;

    Console.WriteLine(Path.GetFileName(info.path) + " : Finished.");

    bgws.Remove(bw); //remove the bw from the list
    //remove events from bw
    bw.DoWork -= (sender, DoWorkEventArgs) => { bwWork(sender, DoWorkEventArgs, info); };
    bw.ProgressChanged -= (sender, ProgressChangedEventArgs) => { bwProgressChanged(sender, ProgressChangedEventArgs, info); };
    bw.RunWorkerCompleted -= (sender, RunWorkerCompletedEventArgs) => { bwCompleted(sender, RunWorkerCompletedEventArgs, info); };
    //dispose bw
    bw.Dispose();
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    if (bgws.Count == 0) //if there are no more bw's, we're good to go
    {
        MessageBox.Show("Done.");
        bgws.Clear();
        _workerCompleted.Set();
    }

}

所以最后,我希望所有后台工作人员在打印出“嘿”之前完成他们正在做的事情。我尝试使用AutoResetEvent和ManualResetEvent,但它们出现时似乎没有任何事情发生。我的意思是,当我把他们包括在内时,没有一个后台工作人员跑了。

我会调用一个帖子,但我有点不情愿,因为我被告知后台工作人员在进行后台工作和更新UI时会使用它。有什么方法可以让我等三个后台工作人员继续我的课程吗?

3 个答案:

答案 0 :(得分:1)

我认为问题在于BackgroundWorker在单独的线程上执行DoWork,但使用创建它的线程来运行ProgressChangedRunWorkerCompleted事件,以便他们可以更新UI 。但是如果您已经将UI线程绑定在WaitOne或其他旋转中,则无法执行这些事件。

bwCompleted bgws.Count == 0时,为什么不打电话给methodA_AfterDone来处理methodA的阅读,然后methodA结束SHOW VARIABLES LIKE '%wait%'; BW3?

答案 1 :(得分:0)

知道我迟到了两年,但这是我在类似情况下所做的。 创建一个完成的计数器。 每当列表中的BGW完成时,就向完成的计数器添加1。 进行了单独的MonitorBGW设置,并设置了while循环,如下所示。

While(CompletedCounter < ListBGWs.Count){Thead.Sleep(2000)}
//Put my code I wanted run after they all completed here.

希望这对某人有帮助:)

答案 2 :(得分:-1)

很简单,您不使用BackgroundWorker并切换到“任务”。 Task.Run(() => Your work );在您这样做之后,您可以使用Task.WaitAll(task1,task2);您可以切换任何EAP to Tasks。通过异步,您可以轻松完成此任务。