Guest User

Untitled

a guest
Dec 14th, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.30 KB | None | 0 0
  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4.  
  5. /// <summary>
  6. /// CancelKey の受付。
  7. ///
  8. /// <code><![CDATA[
  9. /// using (var ck = CancelKey.Create())
  10. /// {
  11. /// ck.Token
  12. /// }
  13. /// ]]></code>
  14. /// </summary>
  15. public static class CancelKey
  16. {
  17. /// <summary>
  18. /// <see cref="Console.CancelKeyPress/> の受付開始。
  19. /// </summary>
  20. /// <returns></returns>
  21. public static CancelKeyRegistration Create() => new CancelKeyRegistration(new CancellationTokenSource());
  22.  
  23. /// <summary>
  24. /// <see cref="Console.CancelKeyPress"/> の購読解除用の disposable。
  25. /// </summary>
  26. public struct CancelKeyRegistration : IDisposable
  27. {
  28. private CancellationTokenSource _cts;
  29. private ConsoleCancelEventHandler _handler;
  30.  
  31. internal CancelKeyRegistration(CancellationTokenSource cts)
  32. {
  33. _cts = cts;
  34.  
  35. var handler = cts.ToCancelEventHandler();
  36. _handler = handler;
  37.  
  38. Console.CancelKeyPress += handler;
  39. }
  40.  
  41. /// <summary>
  42. /// <see cref="Console.CancelKeyPress"/> が発生したときにキャンセルされる<see cref="CancellationToken"/>。
  43. /// </summary>
  44. public CancellationToken Token => _cts.Token;
  45.  
  46. public void Dispose()
  47. {
  48. // Ctrl + C された後にここを通るとデッドロックしてる感じある。
  49. Console.CancelKeyPress -= _handler;
  50. _cts.Dispose();
  51. }
  52. }
  53.  
  54. /// <summary>
  55. /// <see cref="CancellationTokenSource.Cancel"/>を<see cref="ConsoleCancelEventHandler"/>でラップする。
  56. /// </summary>
  57. /// <param name="cts"></param>
  58. /// <returns></returns>
  59. private static ConsoleCancelEventHandler ToCancelEventHandler(this CancellationTokenSource cts) => cts.Cancel;
  60. private static void Cancel(this CancellationTokenSource cts, object sender, ConsoleCancelEventArgs e) => cts.Cancel();
  61. }
  62.  
  63.  
  64. class Program
  65. {
  66. static async Task Main()
  67. {
  68. using (var ck = CancelKey.Create())
  69. {
  70. ck.Token.Register(() => Console.WriteLine("cancelled"));
  71.  
  72. while (!ck.Token.IsCancellationRequested)
  73. {
  74. Console.WriteLine(".");
  75. await Task.Delay(100, ck.Token);
  76. }
  77. Console.WriteLine("a");
  78. }
  79. }
  80. }
Add Comment
Please, Sign In to add comment