Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 此BackgroundWorker当前正忙,无法同时运行多个任务_C#_Wpf_Backgroundworker - Fatal编程技术网

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

C# 此BackgroundWorker当前正忙,无法同时运行多个任务,c#,wpf,backgroundworker,C#,Wpf,Backgroundworker,我试图在WPF应用程序中使用后台工作程序。繁重的任务使用WebClient下载一些HTML并解析其中的一些信息。理想情况下,我希望在下载和解析时不锁定UI,并在UI工作完成后将结果放入UI中 但是,如果我快速提交“下载并解析”命令,就会出现错误: 此BackgroundWorker当前正忙,无法运行多个任务 同时 所以我在谷歌上搜索了一下,似乎我可以启用后台工作程序的.WorkerSupportsCancellation属性,只需.CancelAsync()。但是,这并没有按预期工作(取消当前的

我试图在WPF应用程序中使用后台工作程序。繁重的任务使用WebClient下载一些HTML并解析其中的一些信息。理想情况下,我希望在下载和解析时不锁定UI,并在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()!
}

当我对跟踪异步操作的进度不感兴趣时,我倾向于只在
线程池.QueueUserWorkItem
上打一个lambda,而不是实例化和设置一个后台工作程序,我必须检查它的状态才能正常重用。

在工作程序取消并停止其工作之前,CancelAsync返回。因此,您的RunWorkerAsync调用是在工作程序准备就绪之前启动的,您将收到该错误。您需要先等待工作人员准备就绪。

您需要在开始工作之前进行验证

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

问题是,
CancelAsync()
做它想做的事情:以异步方式取消。这意味着它不会立即停止,而是在一段时间后停止。时间永远无法计算或预测,因此您有两个选择:

  • 通过在循环中等待,直到它的属性变为
    false,等待该
    反向工作者
    真正停止

  • 或者,我认为,更好的解决方案是启动另一个
    后台工作人员
    ,考虑到取消请求已经发送到第一个,所以它将很快或稍后停止。在这种情况下,您需要知道数据来自哪个
    后台工作者,以便处理它或不处理它,因为在第二个开始时,第一个后台工作者仍将运行,并从
    WebService
    泵送数据


  • 希望这有帮助。

    您正在调用CancelAsync,而无需等待后台工作人员实际取消工作。此外,你必须有自己的逻辑来取消工作。有一个很好的例子说明了如何做到这一点。基本上,在parseanddownloadresult()方法中,您需要检查属性。

    调用
    CancelAsync
    仍将触发
    RunWorkerCompleted
    事件。在这种情况下,您需要通过检查
    e.Cancelled
    ,确保未调用
    CancelAsync
    。在触发此事件之前,您无法调用
    RunWorkerAsync

    或者,我建议您按照Tigran的建议做,每次创建一个新的
    BackgroundWorker

    此外,我建议将
    \u backgroundWorker\u DoWork
    的结果存储在
    e.Result
    中,然后从
    \u backgroundWorker\u 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()!
    }
    

    这将导致长串的模式消息框,用户无法从中逃脱。