如何使用CancellationToken属性?

与前面的RulyCanceler类相比 ,我想用CancellationTokenSource来运行代码。

如何在取消令牌中使用它,即不抛出/捕获exception? 我可以使用IsCancellationRequested属性吗?

我试图像这样使用它:

 cancelToken.ThrowIfCancellationRequested(); 

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

但是这给了cancelToken.ThrowIfCancellationRequested();的运行时错误cancelToken.ThrowIfCancellationRequested(); 在方法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:\xxx\Token.cs:line 33 at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:\xxx\Token.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:

 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(); } } } } 

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

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

而已。 你总是需要自己处理取消 – 退出方法,当它是适当的时候退出(以便您的工作和数据是一致的状态)

更新:我不喜欢写while (!cancelToken.IsCancellationRequested)因为经常有几个退出点可以在循环体内安全地停止执行,而循环通常有一些逻辑条件退出(遍历集合中的所有项目等)。 所以我相信最好不要混合这些条件,因为他们有不同的意图。

你可以像这样使用它:

  var cancelToken = new CancellationTokenSource(); Task.Factory.StartNew(() => DoExternalWork(), cancelToken.Token); Thread.Sleep(1000); //simulate some other work //this stops the Task: cancelToken.Cancel(false); 

@ BrainSlugs83

你不应该盲目地信任在stackoverflow上发布的所有东西。 Jens代码中的注释不正确,该参数不控制是否抛出exception。

MSDN非常清楚这个参数控制了什么,你读过吗? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx

如果throwOnFirstException为true,那么exception将立即传播到Cancel之外,从而阻止处理剩余的callback和可取消的操作。 如果throwOnFirstException为false,则此重载将聚合抛出到AggregateException中的任何exception,从而导致引发exception的一个callback不会阻止执行其他已注册的callback。

variables名称也是错误的,因为在CancellationTokenSource上调用Cancel而不是令牌本身,并且源更改它pipe理的每个令牌的状态。

您可以使用ThrowIfCancellationRequested而不处理exception!

ThrowIfCancellationRequested的使用意味着从任务内使用。 在任务中使用时,您不必自己处理exception(并获取未处理的exception错误)。 这将导致离开任务,Task.IsCancelled属性将为True。 不需要任何exception处理。

在您的具体情况下,将线程更改为任务。

 try { var t = new Task(() => Work(cancelSource.Token)); t.Start(); } if (t.IsCancelled) Console.WriteLine("Canceled!"); } 

你可以创build一个带有取消标记的任务,当你的应用程序转到后台时,你可以取消这个标记。

你可以在PCL中做到这一点https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle/

 var cancelToken = new CancellationTokenSource(); Task.Factory.StartNew(async () => { await Task.Delay(10000); // call web API }, cancelToken.Token); //this stops the Task: cancelToken.Cancel(false); 

另一种解决scheme是用户定时器在Xamarin.Forms,当应用程序转到后台停止计时器https://xamarinhelp.com/xamarin-forms-timer/