【问题标题】:Cancelling background worker tasks [duplicate]取消后台工作任务[重复]
【发布时间】:2017-07-28 06:11:15
【问题描述】:

我有一个执行耗时任务的后台工作人员,但我遇到了取消问题,因为我只能标记取消而不实际终止进程。为了解决这个问题,我尝试在要退出的繁重函数中放置一些检查点,但似乎效率不高。 我的代码如下所示:

在重功能的某些点上,我放了这两行:

if (general.backgroundWorker1.CancellationPending)
{ 
   return;
}

private void button4_Click(object sender, EventArgs e) //button invokes heavy function
{
    if (!backgroundWorker1.IsBusy)
        backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    heavyFunction(this);
    if (backgroundWorker1.CancellationPending)
    {
        e.Cancel = true;
        return;
    }
}

private void backgroundWorker1_RunWorkerCompleted_1(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        statusLabel.Text = "Status: cancelled";
    }
    else if (e.Error != null)
    {
        statusLabel.Text = "ERROR!";
    }
    else
    {
        some code;
    }
}

private void cancelSDoutLoop_Click(object sender, EventArgs e)
{
    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync();
    }
}

【问题讨论】:

  • “调用取消”是什么意思?这不是一个真正的术语。
  • general 传递给方法 heavyFunctionForm 对象?
  • 是的,确实如此。抱歉没有澄清
  • 检查CancellationPending 并返回只有当代码可以执行时才有用。在您的heavyFunction(this) 电话返回之前它不能这样做。您需要将取消上下文(例如 BackgroundWorker 对象一直传递到您希望能够中断工作人员的每个点。请参阅标记的重复项以进行一些讨论,以及 Stack Overflow 上的许多其他 BackgroundWorker 问题.
  • 作为骗子关闭,但作为总结:是的,取消必须是合作的。您的代码不需要它是即时的。

标签: c# multithreading visual-studio backgroundworker


【解决方案1】:

Cancel 可能是一个复杂的功能实现,并且通常是事后才想到的。

如果您想取消heavyFunction(应该是longRunningFunction ;),它必须具备取消意识。你说你已经设置了检查点,这是有道理的。

您可以尝试使用更多接受取消令牌的可取消方法调用。例如 Task.Delay 有两个重载:

Delay(TimeSpan)

Delay(TimeSpan, CancellationToken)

另一种策略是将方法拆分为更小、更短的任务。

最后,取消操作不必是瞬时的。 您最终可能会出现“正在取消...”状态,等待停止工作的好时机。

【讨论】:

    猜你喜欢
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多