如何使用 CancellationToken 属性? [英] How to use the CancellationToken property?

查看:27
本文介绍了如何使用 CancellationToken 属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相比前面的代码对于类RulyCanceler,我想运行代码使用 CancellationTokenSource.

Compared to the preceding code for class RulyCanceler, I wanted to run code using CancellationTokenSource.

我如何使用 取消令牌 中提到的,即不抛出/捕捉异常?我可以使用 IsCancellationRequested 属性吗?

How do I use it as mentioned in Cancellation Tokens, i.e. without throwing/catching an exception? Can I use the IsCancellationRequested property?

我尝试这样使用它:

cancelToken.ThrowIfCancellationRequested();

try
{
  new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
  Console.WriteLine("Canceled!");
}

但是这在方法 Work(CancellationToken cancelToken) 中的 cancelToken.ThrowIfCancellationRequested(); 上给出了一个运行时错误:

but this gave a run-time error on cancelToken.ThrowIfCancellationRequested(); in method Work(CancellationToken cancelToken):

System.OperationCanceledException was unhandled
  Message=The operation was canceled.
  Source=mscorlib
  StackTrace:
       at System.Threading.CancellationToken.ThrowIfCancellationRequested()
       at _7CancellationTokens.Token.Work(CancellationToken cancelToken) in C:xxxToken.cs:line 33
       at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:xxxToken.cs:line 22
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

我成功运行的代码在新线程中捕获到了OperationCanceledException:

The code that I successfully ran caught the OperationCanceledException in the new thread:

using System;
using System.Threading;
namespace _7CancellationTokens
{
  internal class Token
  {
    private static void Main()
    {
      var cancelSource = new CancellationTokenSource();
      new Thread(() =>
      {
         try
         {
           Work(cancelSource.Token); //).Start();
         }
         catch (OperationCanceledException)
         {
            Console.WriteLine("Canceled!");
         }
         }).Start();

      Thread.Sleep(1000);
      cancelSource.Cancel(); // Safely cancel worker.
      Console.ReadLine();
    }
    private static void Work(CancellationToken cancelToken)
    {
      while (true)
      {
        Console.Write("345");
        cancelToken.ThrowIfCancellationRequested();
      }
    }
  }
}

推荐答案

您可以按如下方式实现您的工作方法:

You can implement your work method as follows:

private static void Work(CancellationToken cancelToken)
{
    while (true)
    {
        if(cancelToken.IsCancellationRequested)
        {
            return;
        }
        Console.Write("345");
    }
}

就是这样.你总是需要自己处理取消——在适当的时候退出方法退出(这样你的工作和数据处于一致的状态)

That's it. You always need to handle cancellation by yourself - exit from method when it is appropriate time to exit (so that your work and data is in consistent state)

更新:我不喜欢写 while (!cancelToken.IsCancellationRequested) 因为通常很少有退出点可以在循环体中安全地停止执行,并且通常循环有一些逻辑条件退出(迭代集合中的所有项目等).所以我认为最好不要混合这些条件,因为它们的意图不同.

UPDATE: I prefer not writing while (!cancelToken.IsCancellationRequested) because often there are few exit points where you can stop executing safely across loop body, and loop usually have some logical condition to exit (iterate over all items in collection etc.). So I believe it's better not to mix that conditions as they have different intention.

关于避免CancellationToken.ThrowIfCancellationRequested()的注意事项:

Cautionary note about avoiding CancellationToken.ThrowIfCancellationRequested():

有问题的评论来自 埃蒙·内博恩:

... 用一系列对 IsCancellationRequested 的检查替换 ThrowIfCancellationRequested 优雅地退出,正如这个答案所说.但这不仅仅是一个实现细节;影响可观察行为:任务将不再以取消状态结束,而是以 RanToCompletion 结束.这不仅会影响显式状态检查,而且会更微妙地影响任务链接,例如ContinueWith,取决于使用的 TaskContinuationOptions.我会说避免 ThrowIfCancellationRequested 是危险的建议.

... replacing ThrowIfCancellationRequested with a bunch of checks for IsCancellationRequested exits gracefully, as this answer says. But that's not just an implementation detail; that affects observable behavior: the task will no longer end in the cancelled state, but in RanToCompletion. And that can affect not just explicit state checks, but also, more subtly, task chaining with e.g. ContinueWith, depending on the TaskContinuationOptions used. I'd say that avoiding ThrowIfCancellationRequested is dangerous advice.

这篇关于如何使用 CancellationToken 属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆