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

C# 我如何知道多个后台工作人员何时完成?,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,现在我有一个方法,它调用不同的方法三次 List<BackgroundWorker> bgws = new List<BackgroundWorker>(); AutoResetEvent _workerCompleted = new AutoResetEvent(false); void methodA () { methodB(); //bw1 methodB(); //bw2 methodB(); //bw3 //wait for

现在我有一个方法,它调用不同的方法三次

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

}
所以最后,我希望所有的背景工作人员在“嘿”被打印出来之前完成他们正在做的事情。我尝试使用AutoResetEvent和ManualResetEvent,但当它们出现时,似乎什么也没有发生。我的意思是,当我把背景工作人员包括进来时,他们甚至都没有参加


我会调用一个线程,但我有点不情愿,因为我被告知在做后台工作和更新UI时要使用后台工作人员。有没有什么方法可以让我等待三个后台工作人员,这样我就可以继续我的程序?

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


在您的
bwCompleted
中,当
bgws.Count==0
时,为什么不调用
methodA_\u AfterDone
来处理
methodA
的读取,然后让
methodA
在bw3之后结束?

很简单,您不需要使用BackgroundWorker并切换到任务<代码>任务。运行(()=>您的工作)完成后,可以使用
Task.WaitAll(task1,task2)您可以切换任何设置。使用async,您可以轻松实现这一点。

知道我迟到了两年,但这是我在类似情况下所做的。 创建了一个完整的计数器。 每次完成列表中的
BGW
时,向已完成计数器添加一个。 有一个单独的
监视器bgw
设置,带有一个while循环,类似于下面的内容

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

希望这对某人有所帮助:)

您是否在让后台工作人员实际执行任务时遇到问题,或者您在与所有工作人员同步和检测所有工作人员何时完成时遇到问题?我不清楚你到底有什么问题,对此我很抱歉。因此,如果我在程序中包含
AutoResetEvent
部分,那么后台工作人员都不会做任何事情。如果我不包括它,后台工作人员工作得很好,但是
Console.WriteLine(“嘿”)是在工作人员完成工作之前执行的。我想我可以在检查后台工作列表是否为空的部分添加更多代码,但是我还有很多代码要处理,我觉得这会扰乱程序的流程。我只想让背景工作人员完成他们的工作,然后继续写那条writeline语句。澄清:背景工作人员什么都不做(即,
bwWork
从未执行),或者他们做他们的工作,但是永远不要发出完全完成的信号,这样代码就会永远等待?您似乎在
bwCompleted
中做一些不必要的工作-为什么要在即将
处理对象时删除事件?为什么
Clear()
当您已经知道
bgws
列表是清晰的时,它会出现?很有趣。我很高兴你指出了这一点<代码>bwork
是程序中包含
自动resetEvent
部件时执行的三个事件中的唯一一个。进度没有改变,完成的事件也没有因为某种原因被执行。啊,我想这是一种方法。我真的很想继续我最初启动bw的地方,但如果我不能,那也没关系。@Tim或者,你可以同时做两件事:保留你的后台工作程序,但创建尽可能多的TaskCompletionSource,并在RunWorkerCompleted事件中将它们转换为completed。从那里,你可以等待一项任务。当所有任务都在你的任务列表上时,从你开始的地方继续them@KevinGosse我的意思是你可以,但是你为什么要费心重新创建你自己效率较低的
任务。在你可以使用
任务的情况下运行
实现。运行
@Servy我刚刚做了一次搜索,了解了
进度
,我不知道TPL有办法报告进展。因此,实际上,坚持使用BackgroundWorkerTask没有任何意义。task不能保证任务运行在不同的线程上——它可能运行在同一个线程上,因此它可能会占用UI线程。task不会占用UI线程,但“task.run”将运行在不同的线程上,并且不会阻塞UI。正如我所说,你可以用一个任务包装BackgroundWorker,这样他就可以使用Task.WaitAll或Task。什么时候所有任务都可以保证进度事件在UI线程上运行?@NetMage TPL中有这样做的工具,是的。@NetMage TPL是多年来执行长时间运行的后台操作的推荐方法。关于进展,你可以看一看
While(CompletedCounter < ListBGWs.Count){Thead.Sleep(2000)}
//Put my code I wanted run after they all completed here.