此BackgroundWorker当前正忙,无法同时运行多个任务

问题描述 投票:0回答:4

如果我单击启动后台工作程序两次的按钮,则会收到此错误。

This BackgroundWorker is currently busy and cannot run multiple tasks concurrently

如何避免这种情况?

c# backgroundworker
4个回答
106
投票

简单:不要启动BackgroundWorker两次。

您可以使用

IsBusy
属性检查它是否已经在运行,因此只需更改以下代码:

worker.RunWorkerAsync();

对此:

if( !worker.IsBusy )
    worker.RunWorkerAsync();
else
    MessageBox.Show("Can't run the worker twice!");

更新:

如果你确实需要同时启动多个后台任务,你可以简单地创建多个BackgroundWorker对象


54
投票

为您要执行的每个操作创建一个新的BackgroundWorker 对象。即,而不是:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
for (int i; i < max; i++) {
   worker.RunWorkerAsync(i);
}

试试这个:

for (int i; i < max; i++) {
   BackgroundWorker worker = new BackgroundWorker();
   worker.DoWork += new DoWorkEventHandler(worker_DoWork);
   worker.RunWorkerAsync(i);
}

6
投票

我会考虑对需要完成的任务进行排队。您将获得以下优势:

  • 您不必处理后台任务因其他程序已在运行而无法启动的问题
  • 通过为每个任务创建一个新的背景,您不必担心使用太多线程。
  • 最后,队列可以让您确保后台任务按照创建/请求的顺序运行。
这是一个示例实现:

链接。我不确定该实现是否是线程安全的,一旦我弄清楚我正在使用的实现中当前的锁定问题,我将更新我的答案。


2
投票
虽然不是OP最初询问的情况,但如果您以某种生产者-消费者模式使用后台工作人员,这也可能由于竞争条件而发生(现在发生在我身上,并寻找答案)。

示例:

if (BckgrndWrkr == null) { BckgrndWrkr = new BackgroundWorker(); BckgrndWrkr.DoWork += DoWorkMethod; BckgrndWrkr.RunWorkerAsync(); } else if (!BckgrndWrkr.IsBusy) { BckgrndWrkr.RunWorkerAsync(); }

在这种情况下,存在竞争条件:第一个实例实例化一个新的后台工作程序,第二个实例到达

else if

 并启动后台工作程序,在第一个实例到达 
if
 块的 RunWorkerAsync 之前,当它到达时,它会抛出错误。 

可以通过向整个 if + if else 部分添加锁来避免这种情况。

© www.soinside.com 2019 - 2024. All rights reserved.