【问题标题】:How do I safely cancel a Task?如何安全地取消任务?
【发布时间】:2018-06-04 14:55:18
【问题描述】:

所以我有这个任务,它从单击一个按钮开始,我想知道如何安全地取消这个任务的循环?

private async Task RunAsync()
{
    PerformanceCounter counter = new PerformanceCounter("Process", "% Processor Time", pServer.ProcessName, true);
    Random r = new Random();
    while (true)
    {
        float pct = counter.NextValue() / 10f;
        ServerCPU = pct.ToString("0.0");
        await Task.Delay(2000);
    }
}

点击启动任务循环的按钮后,如何取消?

【问题讨论】:

  • 使用CancellationToken

标签: c# .net asynchronous async-await task


【解决方案1】:

与处理Threads 时不同,如果没有Task 的合作,您将无法取消/中止它。这就是CancellationTokenCancellationTokenSource 发挥作用的地方。

您应该将CancellationToken 传递给RunAsync 并检查是否明确请求取消,当它有意义时。在您的示例中,我可能会在每次迭代中都这样做:

private async Task RunAsync(CancellationToken ct)
{
    PerformanceCounter counter = new PerformanceCounter("Process", "% Processor Time", pServer.ProcessName, true);
    Random r = new Random();
    while (true)
    {
        ct.ThrowIfCancellationRequested();

        float pct = counter.NextValue() / 10f;
        ServerCPU = pct.ToString("0.0");
        await Task.Delay(2000, ct);
    }
}

在来电者网站上,您应该使用CancellationTokenSource。它会给你一个Token 传递给RunAsync 以及触发取消的方法:

var cts = new CancellationTokenSource();
RunAsync(cts.Token);

// when you want to cancel it the task:
cts.Cancel();

您可以在Cancellation in Managed Threads 中阅读有关该模式的更多信息。

【讨论】:

  • 您也可以将CancellationToken 传递给Task.Delay 调用。
  • 你真的不应该取消一个线程,即使你可以。这是一件坏事。
  • 为什么不直接检查ct.IsCancellationRequestedexit 循环呢?为什么.ThrowIfCancellationRequested()
  • @Enigmativity “你真的不应该取消一个线程,即使你可以。这是一件坏事。” - 为什么?
  • @MineR - 在线程上调用 .Abort() 会导致 .NET 运行时进入未定义状态,从而可能导致当前 AppDomain 中的所有其他线程无法按预期运行。调用.Abort() 只应在尝试强制崩溃整个应用程序时使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
相关资源
最近更新 更多