55

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

This BackgroundWorker is currently busy and cannot run multiple tasks concurrently

我怎样才能避免这种情况?

4

4 回答 4

101

很简单:不要启动 BackgroundWorker 两次。

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

worker.RunWorkerAsync();

对此:

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

更新:

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

于 2009-02-25T22:14:02.117 回答
53

为您要执行的每个操作创建一个新的 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);
}
于 2009-03-21T01:20:00.247 回答
7

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

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

这是一个示例实现:http ://thevalerios.net/matt/2008/05/a-queued-backgroundworker 。我不确定是否在线程安全中实现,一旦我弄清楚我正在使用的实现中的当前锁定问题,我将更新我的答案。

于 2010-08-26T11:07:06.317 回答
1

尽管 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 部分添加锁来避免。

于 2018-04-24T14:02:45.000 回答