C#-背景工人';s CancelAsync()不工作?

C#-背景工人';s CancelAsync()不工作?,c#,backgroundworker,C#,Backgroundworker,我想中止进程,但无法这样做,我正在使用后台工作程序处理我的函数 public void Init() { bw = new BackgroundWorker(); bw.WorkerSupportsCancellation = true; bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_Run

我想中止进程,但无法这样做,我正在使用后台工作程序处理我的函数

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()
正在执行处理部分并返回结果

请给我任何解决方案


谢谢。

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

  • 长时间运行的
    abd()
    方法完成了它的工作,并且没有什么可以取消的
  • abd()
    开始工作,后台工作程序被阻止-它正在等待
    abd()
    的结果,然后继续执行-即退出
    if else
    阻止并引发
    RunWorkerCompleted
    事件
  • 几乎不可能的选项-您将以极快的速度前进,并且您将单击
    之前的按钮(如果其他
    块输入)。然后,
    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
}
void bw\u DoWork(对象发送方,DoWorkEventArgs e)
{
列表结果=新列表();
//这里有任何循环-foreach,while
对于(int i=0;i
可能
DoWork
在调用
CancelAsync
之前已经完成了它的工作,如文档
e中所述。Cancelled
可能为false

说这个

请注意,DoWork事件处理程序中的代码可能会完成其任务 正在发出取消请求,并且您的轮询循环 可能无法将CancellationPending设置为true。在这种情况下 中System.ComponentModel.RunWorkerCompletedEventArgs的取消标志 您的RunWorkerCompleted事件处理程序将不会设置为true,甚至 尽管有人提出取消申请。这种情况被称为 竞态条件和是多线程编程中常见的问题


下面呢

While(!bw.CancellationPending)
{
   //do some work!
}
e.Cancel = true;

看起来函数
abd()
占用了太多的处理时间,您希望在两者之间中止它

private Thread _backgroundWorkerThread;

public void AbortBackgroundWorker()
{
    if(_backgroundWorkerThread != null)
    _backgroundWorkerThread.Abort();
}

void DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
    _backgroundWorkerThread = Thread.CurrentThread;

    // call abd...

    }
    catch(ThreadAbortException)
    {
        // Do your clean up here.
    }
}
AbortBackgroundWorker()
放入
btncan\u单击事件。

但这是有代价的。现在RunWorkerCompleted事件将不起作用。因此,您必须在catch块中处理它,或者编写一些我们自己的代码。

过程在哪里?你有一些循环工作方法吗?当前backgroundworker在您单击按钮之前完成了它的工作,并请正确格式化您的代码:)当主线程终止时,后台工作程序不是中止了吗?我认为您必须多次检查,才能取消异步运行的后台工作程序…函数abd()正在执行处理并返回结果感谢您的帮助,但它也无法正常工作,因为我已使用两步循环对其进行了测试。当我在启动后中止它时,它不是被中止,而是停止执行下一步。因此,如果您有任何进一步的解决方案,请告知。@neelb2是的,它应该是这样工作的-当前步骤将被执行,进一步的步骤将被取消。我只是想在进程暂停或停止之间中断它。