13

我想中止该过程但无法这样做,我正在使用具有处理功能的后台工作人员。

public void Init()
{
    bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    if (bw.CancellationPending == true)
    {
        e.Cancel = true;
    }
    else
    {
        e.Result = abd();
    }
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(e.Cancelled)
    {
        lbltext.content="Canceled";
    }

    else
    {
        lbltext.content="Completed";
    }
}

private void btncan_Click(object sender, RoutedEventArgs e)
{
    bw.CancelAsync();
}

private void btnstart_Click(object sender, RoutedEventArgs e)
{
    bw.RunWorkerAsync();
}

我无法使用此代码中止该过程。函数abd()正在执行处理部分并返回结果。

请给我任何解决方案。

谢谢。

4

3 回答 3

17

当您打电话时,bw.CancelAsync()您只需将CancellationPending标志设置为true. 默认情况下它不会取消某些内容。您需要手动处理挂起的取消。但是你不能用你的代码做到这一点,因为当你点击按钮时,有三个可能的选项:

  • 长时间运行的abd()方法完成了它的工作,没有什么可以取消
  • abd()开始它的工作,后台工作人员被阻止 - 它正在等待结果abd(),然后它继续执行 - 即退出if-else块并引发RunWorkerCompleted事件。
  • 几乎不可能的选项 - 您将轻而易举,并且您将在if-else输入块之前单击按钮。比CancellationPending将是真实的,并且abd()不会开始执行

如果您想使用取消,请在循环中执行长时间运行的任务,并检查每个步骤是否有取消:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    List<Foo> results = new List<Foo>();

    // any loop here - foreach, while
    for(int i = 0; i < steps_count; i++)
    {    
         // check status on each step
         if (bw.CancellationPending == true) 
         {
             e.Cancel = true;
             return; // abort work, if it's cancelled
         }

         results.Add(abd()); // add part of results
    }

    e.Result = results; // return all results
}
于 2013-08-19T13:25:14.217 回答
1

可能DoWork在调用之前可能已经完成了工作,CancelAsync并且如文档中所述e.Cancelled可能是错误的..

文档这样说

请注意,您在 DoWork 事件处理程序中的代码可能会在发出取消请求时完成其工作,并且您的轮询循环可能会错过将 CancellationPending 设置为 true 的情况。在这种情况下,您的 RunWorkerCompleted 事件处理程序中 System.ComponentModel.RunWorkerCompletedEventArgs 的 Canceled 标志不会设置为 true,即使已发出取消请求。这种情况称为竞争条件,是多线程编程中常见的问题。

于 2013-08-19T13:30:56.917 回答
0

下面的呢?

While(!bw.CancellationPending)
{
   //do some work!
}
e.Cancel = true;
于 2013-08-19T13:42:42.543 回答