C# 此BackgroundWorker当前正忙,无法同时运行多个任务
如果单击两次启动backgroundworker的按钮,就会出现此错误C# 此BackgroundWorker当前正忙,无法同时运行多个任务,c#,backgroundworker,C#,Backgroundworker,如果单击两次启动backgroundworker的按钮,就会出现此错误 This BackgroundWorker is currently busy and cannot run multiple tasks concurrently 如何避免这种情况?很简单:不要启动BackgroundWorker两次 This BackgroundWorker is currently busy and cannot run multiple tasks concurrently 您可以使用IsBus
This BackgroundWorker is currently busy and cannot run multiple tasks concurrently
如何避免这种情况?很简单:不要启动BackgroundWorker两次
This BackgroundWorker is currently busy and cannot run multiple tasks concurrently
您可以使用IsBusy
属性检查它是否已在运行,因此只需更改此代码:
worker.RunWorkerAsync();
为此:
if( !worker.IsBusy )
worker.RunWorkerAsync();
else
MessageBox.Show("Can't run the worker twice!");
更新:
如果确实需要同时启动多个后台任务,只需创建多个BackgroundWorker对象即可为要执行的每个操作创建一个新的BackgroundWorker对象。即,而不是:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
for (int i; i < max; i++) {
worker.RunWorkerAsync(i);
}
BackgroundWorker-worker=新的BackgroundWorker();
worker.DoWork+=新的doworkereventhandler(worker\u DoWork);
用于(int i;i
试试这个:
for (int i; i < max; i++) {
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(i);
}
for(int i;i
我会把需要完成的任务排成队列。您可以获得以下优势
- 您不必处理由于其他正在运行的任务而无法启动后台任务的问题
- 通过为每个任务创建一个新的后台,您不必担心会占用太多线程
- 最后,队列允许您确保后台任务按照创建/请求的顺序运行
下面是一个示例实现:。我不确定该实现是否在threadsafe中,一旦我在正在使用的实现中解决了当前的锁定问题,我将更新我的答案 虽然不是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部分中添加一个锁来避免。在某种程度上,我同意答案并非完全有用。如果您确实需要运行两个后台进程,那么得到一个错误并不是很好,它会说“不能运行工作进程两次”。我会假设关于为每个任务运行新的backgroundWorkers的答案——或者以某种方式查询作业是一个更好的解决方案,这不会导致您必须检查系统的其他部分是否已启动后台作业并对此采取行动。
IsBusy
何时才能清除?我本以为它会在RunWorkerCompleted
事件触发之前被清除,但事实似乎并非如此(至少基于我的实验)。我认为OP的问题从未得到回答。虽然我想我确实解决了部分问题。我使用了一个TcpListener,在没有挂起cncel的情况下,接受连接。所以我在想办法打断那个电话。OP可能需要提供更多关于他对后台工作人员所做的事情的信息,以确定是什么阻碍了他。@omJohn8372-如果您在后台工作人员中使用TcpListeners时遇到问题,我建议您不要这样做。在TcpListener上使用异步方法,使事情异步运行,并释放主线程来做其他事情。大多数异步方法都使用CancellationToken,您可以使用它在任何时候关闭它们,如果您需要的话desire@OrionEdwards我很感激你的建议,这是一个很好的建议。我不能正确地回忆起我做了什么来修复它,但我确实修复了它,而不是仅仅扔掉旧的物体,重新开始。我没有在TcpListener上完整地使用异步方法,我想我应该——我以前偶然发现过它们,它们似乎是处理问题的简洁方法。这是一个很好的答案。如果需要的话,我们如何杀死所有的后台工作人员?@VladSpreys我不能仅仅在评论中讨论线程取消,但是在这个网站上有一些关于这个主题的非常好的帖子。@fatcat1111谢谢。如果我们保留一个引用,我理解取消线程的想法。但是对于这个代码片段,我们不需要。@vladpreys如果您想要一个对worker的引用列表,那么在for循环之外声明一个列表,在循环中,实例化worker之后,将其添加到列表中。然后,如果您需要取消这些变量,请浏览列表,并以最适合您的方案的方式取消每个变量。请不要这样命名您的变量。指向示例实现的链接已断开