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

Onl*_*ere 0 c# wpf 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()!
}
Run Code Online (Sandbox Code Playgroud)

cad*_*ll0 6

通话CancelAsync仍然会激活此RunWorkerCompleted事件.在这种情况下,您需要CancelAsync通过检查确保尚未调用e.Cancelled.在此事件发生之前,您无法致电RunWorkerAsync.

或者,我建议你做Tigran建议的,BackgroundWorker每次创建一个新的.

此外,我建议存储_backgroundWorker_DoWorkin 的结果e.Result,然后从中检索它们_backgroundWorker_RunWorkerCompleted

也许这样的事情

BackgroundWorker _backgroundWorker;

private BackgroundWorker CreateBackgroundWorker()
{
    var bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += _backgroundWorker_DoWork;
    bw.RunWorkerCompleted += new  _backgroundWorker_RunWorkerCompleted;
    return bw.
}

private void LoadHtmlAndParse(string foobar)
{
    //Cancel whatever it is you're doing!
    if (_backgroundWorer != null)
    {
        _backgroundWorker.CancelAsync();
    }

    _backgroundWorker = CreateBackgroundWorker();

    //And start doing this immediately!
    _backgroundWorker.RunWorkerAsync(foobar);
}

//you no longer need this because the value is being stored in e.Result
//POCOClassFoo foo = new POCOClassFoo();

private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        //Error handling goes here.
    }
    else
    {
        if (e.Cancelled)
        {
            //handle cancels here.
        }
        {
            //This automagically sets the UI to the data.
            Foo.DataContext = (POCOClassFoo)e.Result;
        }
}

private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    //DOING THE HEAVY LIFTING HERE!
    e.Result = parseanddownloadresult()!
}
Run Code Online (Sandbox Code Playgroud)


Tig*_*ran 5

事情就是它CancelAsync()所做的事情:以异步的方式取消.这意味着它不会立即停止,但过了一段时间.那段时间永远无法计算或预测,所以你有几个选择:

  1. 等到这真的backround worker停止,通过循环等待直到它的IsBusy属性变为false

  2. 或者,我认为,更好的解决方案是启动另一个background worker,考虑到取消请求已经发送到第一个,所以它将很快或稍后停止.在这种情况下,您需要知道从哪个 background worker数据到来,为了处理它,在第二个数据开始时,第一个数据仍将运行并从中抽取数据WebService.

希望这可以帮助.