此BackgroundWorker当前正忙,无法同时运行多个任务
我正在尝试在 WPF 应用程序中使用后台工作人员。这项繁重的任务使用 WebClient 下载一些 HTML 并从中解析一些信息。理想情况下,我希望在不锁定 UI 的情况下进行下载和解析,并在完成工作后将结果放入 UI 中。
它工作正常,但是,如果我快速提交“下载并解析”命令,我会收到错误:
此BackgroundWorker当前正忙,无法运行多个任务 同时
所以我做了一些谷歌搜索,似乎我可以启用后台工作人员的 .WorkerSupportsCancellation
属性,并且只需 .CancelAsync()
。但是,这并不能按预期工作(取消当前的下载和解析)。
我仍然收到上述错误。
这是我的代码:
//In window constructor.
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
//Declared at class level variable.
BackgroundWorker _backgroundWorker = new BackgroundWorker();
//This is the method I call from my UI.
private void LoadHtmlAndParse(string foobar)
{
//Cancel whatever it is you're doing!
_backgroundWorker.CancelAsync();
//And start doing this immediately!
_backgroundWorker.RunWorkerAsync(foobar);
}
POCOClassFoo foo = new POCOClassFoo();
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//This automagically sets the UI to the data.
Foo.DataContext = foo;
}
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//DOING THE HEAVY LIFTING HERE!
foo = parseanddownloadresult()!
}
I'm trying to use a Background Worker in a WPF application. The heavy lifting task uses WebClient to download some HTML and parse some info out of it. Ideally I want to do that downloading and parsing without locking the UI and placing the results in the UI once it's done working.
And it works fine, however, if I quickly submit the "download and parse" command, I get the error:
This BackgroundWorker is currently busy and cannot run multiple tasks
concurrently
So I did some Googling and it seems that I can enable the .WorkerSupportsCancellation
property of the background worker and just .CancelAsync()
. However, this doesn't work as expected (canceling the current download and parse).
I still get the above error.
Here's my code:
//In window constructor.
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
//Declared at class level variable.
BackgroundWorker _backgroundWorker = new BackgroundWorker();
//This is the method I call from my UI.
private void LoadHtmlAndParse(string foobar)
{
//Cancel whatever it is you're doing!
_backgroundWorker.CancelAsync();
//And start doing this immediately!
_backgroundWorker.RunWorkerAsync(foobar);
}
POCOClassFoo foo = new POCOClassFoo();
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//This automagically sets the UI to the data.
Foo.DataContext = foo;
}
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//DOING THE HEAVY LIFTING HERE!
foo = parseanddownloadresult()!
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
调用
CancelAsync
仍会触发RunWorkerCompleted
事件。在这种情况下,您需要通过检查e.Cancelled
来确保尚未调用CancelAsync
。在此事件触发之前,您无法调用RunWorkerAsync
。或者,我建议您按照 Tigran 的建议进行操作,并每次创建一个新的
BackgroundWorker
。此外,我建议将
_backgroundWorker_DoWork
的结果存储在e.Result
中,然后从_backgroundWorker_RunWorkerCompleted
中检索它们,也许是这样的
Calling
CancelAsync
will still fire theRunWorkerCompleted
event. In this event, you need to make sure thatCancelAsync
has not been called, by checkinge.Cancelled
. Until this event fires, you cannot callRunWorkerAsync
.Alternatively, I would recommend you do what Tigran suggested and create a new
BackgroundWorker
each time.Further more, I would recommend storing the results of
_backgroundWorker_DoWork
ine.Result
, then retrieve them from the same in_backgroundWorker_RunWorkerCompleted
Maybe something like this
问题是
CancelAsync()
做了它喜欢的事情:以异步方式取消。这意味着它不会立即停止,而是在一段时间后停止。该时间永远无法计算或预测,因此您有几个选择:等待这个
后台工作人员
真正停止,通过循环等待直到IsBusy 属性变为false
或者,我认为,更好的解决方案是启动另一个
后台工作程序
,考虑到取消请求已经发送给第一个,所以很快就会或者稍后停止。在这种情况下,您需要知道来自哪个后台工作人员
数据,以便处理它或不处理它,因为在第二个开始时,第一个仍然会运行并泵送来自WebService
的数据。希望这有帮助。
The thing is that
CancelAsync()
does what it climes: cancel in async way. That means that it will not stop immediately, but after some time. That time can never be calculated or predicted, so you have a couple of options:Wait until this
backround worker
stops really, by waiting in cycle until IsBusy property of it becomesfalse
Or, I think, better solution is to start another
background worker
, considering that request of cancelation was already sent to the first one, so it will be soon or later stop. In this case, you need to know from whichbackground worker
data comes, in order to process it or not, cause on start of second the first one will still run and pump the data fromWebService
.Hope this helps.
CancelAsync 在工作线程取消并停止其工作之前返回。因此,您的 RunWorkerAsync 调用在工作线程准备就绪之前开始,并且您会收到该错误。您需要先等待工作人员准备好。
CancelAsync returns before the worker cancels and stops its work. Hence, your RunWorkerAsync call is starting before the worker is ready, and you're getting that error. You'll need to wait for the worker to be ready first.
当我对跟踪异步操作的进度不感兴趣时,我倾向于只在 ThreadPool.QueueUserWorkItem 处调用 lambda,而不是实例化和设置必须检查状态的后台工作线程能够以合理的方式重用。
When I'm not interested in tracking progress of an async operation, I tend to prefer to just slap a lambda at
ThreadPool.QueueUserWorkItem
instead of instantiating and setting up a background worker that I have to check the state of to be able to reuse in a sane way.您需要在开始之前进行验证。
You need to verify before you kicks in.
您正在调用 CancelAsync,而无需等待后台工作人员实际取消工作。此外,您还必须有自己的取消工作的逻辑。 MSDN 上有一个很好的示例,它展示了如何做吧。基本上在您的 parseanddownloadresult() 方法中,您需要检查 CancellationPending 属性。
You are calling CancelAsync without waiting for the background worker to actually cancel the work. Also you must have your own logic for cancelling the work. There is a good example on MSDN which shows how to do it. Basically in your parseanddownloadresult() method you need to check the CancellationPending property.