《CLR via C#》之线程处理——协作式取消和超时

《CLR via C#》之线程处理——协作式取消和超时

协作式取消和超时

创建协作式取消步骤:

  1. 首先创建一个System.Threading.CancellationTokenSource对象。
  1. public sealed class CancellationTokenSource : IDisposable
  2. {
  3. // 一个引用类型
  4. public void Dispose(); // 释放资源(比如WaitHandle)
  5. public Boolean IsCancellationRequested { get; }
  6. public CancellationToken Token { get; }//通过这个属性获得Token并传递给操作。
  7. public void Cancel(); // 内部调用Cancel并传递false
  8. public void Cancel(Boolean throwOnFirstException);
  9. ...
  10. }
  1. 通过CancellationTokenSource.Token属性获得一个或多个CancellationToken,并传递给操作。
  1. public struct CancellationToken
  2. {
  3. // 一个值类型
  4. public static CancellationToken None { get; }
  5. public Boolean IsCancellationRequested{ get; } // 由非通过Task调用的操作调用
  6. public void ThrowIfCancellationRequested(); // 由通过Task调用的操作调用
  7. //CancellationTokenSource 取消时,WaitHandle 会收到信号
  8. public WaitHandle WaitHandle { get; }
  9. public Boolean CanBeCanceled { get; } // 很少使用
  10. public CancellationTokenRegistration Register(Action<Object> callback, Object state,
  11. Boolean useSynchronizationContex); // 未列出更简单的重载版本
  12. }
  1. 需要取消的方法中定期查询IsCancellationRequest属性。
  1. internal static class CancellationDemo
  2. {
  3. public static void Go()
  4. {
  5. CancellationTokenSource cts = new CancellationTokenSource();
  6. cts.Token.Register(() => Console.WriteLine("cancel callbace!!!"));
  7. var restration = cts.Token.Register(o => Console.WriteLine("Cancel callback{0}!!!", o), 5, true);
  8. restration.Dispose();
  9. ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
  10. Console.WriteLine("Press Enter to cancel");
  11. Console.ReadLine();
  12. cts.Cancel();
  13. Console.ReadLine();
  14. }
  15. private static void Count(CancellationToken token, Int32 countTo)
  16. {
  17. for (int count = 0; count < countTo; count++)
  18. {
  19. if (token.IsCancellationRequested)
  20. {
  21. Console.WriteLine("Count is cancelled");
  22. break;
  23. }
  24. Console.WriteLine(count);
  25. Thread.Sleep(200);
  26. }
  27. Console.WriteLine("Count is done");
  28. }
  29. }

PS:如果要执行一个不允许被取消的操作,可以向操作传递CancellationTokenSource.None属性。

  1. 如果需要,可以调用CancellationToken的Register方法,注册取消时的CallBack。可以通过该方法的返回值CallcellationTakenRegistration,调用它的Dispose方法删除注册的回调函数。
  2. 还可以链接另一组CancellationTokenSource来新建一个CancellationTokenSource对象。
  1. var cts1 = new CancellationTokenSource();
  2. cts1.Token.Register(() => Console.WriteLine("cts1 cancelled"));
  3. var cts2 = new CancellationTokenSource();
  4. cts2.Token.Register(() => Console.WriteLine("cts2 canceled"));
  5. //创建一个新的,它在cts1或cts2取消时取消
  6. var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
  7. linkedCts.Token.Register(() => Console.WriteLine("linkedCts canceled"));
  1. 还可以通过CancellationTokenSource的构造器或调用CancelAfter来指定延时时间,到时自动取消。
  1. public sealed class CancellationTokenSource : IDisposable
  2. {
  3. public CancellationTokenSource(Int32 millisecondsDelay);
  4. public CancellationTokenSource(TimeSpan delay);
  5. public void CancelAfter(Int32 millisecondsDelay);
  6. public void CancelAfter(TimeSpan delay);
  7. ...
  8. }




原文地址:https://www.cnblogs.com/qianzi067/p/5815567.html