Advertisement
Guest User

Untitled

a guest
Feb 11th, 2014
439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.37 KB | None | 0 0
  1. // We want:
  2. /*
  3. Before pause requested
  4. Before await pause.WaitWhilePausedAsync()
  5. After pause requested.
  6. After await pause.WaitWhilePausedAsync()
  7. */
  8.  
  9. using System;
  10. using System.Threading.Tasks;
  11.  
  12. namespace ConsoleApplication
  13. {
  14.     class Program
  15.     {
  16.         // http://stackoverflow.com/a/19616899/1768303
  17.         // Based on http://blogs.msdn.com/b/pfxteam/archive/2013/01/13/cooperatively-pausing-async-methods.aspx
  18.  
  19.         public class PauseTokenSource
  20.         {
  21.             private readonly object m_lockObject = new Object();
  22.             bool m_paused = false; // could use m_resumeRequest as flag too
  23.  
  24.             internal static readonly Task s_completedTask = Task.FromResult(true);
  25.             private TaskCompletionSource<bool> m_pauseResponse;
  26.             private TaskCompletionSource<bool> m_resumeRequest;
  27.  
  28.             public void Pause()
  29.             {
  30.                 lock (m_lockObject)
  31.                 {
  32.                     if (m_paused)
  33.                         return;
  34.                     m_paused = true;
  35.                     m_pauseResponse = null;
  36.                     m_resumeRequest = new TaskCompletionSource<bool>();
  37.                 }
  38.             }
  39.  
  40.             public void Resume()
  41.             {
  42.                 TaskCompletionSource<bool> resumeRequest = null;
  43.  
  44.                 lock (m_lockObject)
  45.                 {
  46.                     if (!m_paused)
  47.                         return;
  48.                     m_paused = false;
  49.                     resumeRequest = m_resumeRequest;
  50.                     m_resumeRequest = null;
  51.                 }
  52.  
  53.                 resumeRequest.TrySetResult(true);
  54.             }
  55.  
  56.             public Task WaitWhilePausedAsync()
  57.             {
  58.                 lock (m_lockObject)
  59.                 {
  60.                     if (!m_paused)
  61.                         return s_completedTask;
  62.                     return m_resumeRequest.Task;
  63.                 }
  64.             }
  65.  
  66.             // pause with feedback
  67.             // that the producer task has reached the paused state
  68.  
  69.             public Task PauseWithResponseAsync()
  70.             {
  71.                 Task responseTask = null;
  72.  
  73.                 lock (m_lockObject)
  74.                 {
  75.                     if (m_paused)
  76.                         return m_pauseResponse.Task;
  77.                     m_paused = true;
  78.                     m_pauseResponse = new TaskCompletionSource<bool>();
  79.                     m_resumeRequest = new TaskCompletionSource<bool>();
  80.                     responseTask = m_pauseResponse.Task;
  81.                 }
  82.  
  83.                 return responseTask;
  84.             }
  85.  
  86.             public Task WaitWhilePausedWithResponseAsyc()
  87.             {
  88.                 Task resumeTask = null;
  89.                 TaskCompletionSource<bool> response = null;
  90.  
  91.                 lock (m_lockObject)
  92.                 {
  93.                     if (!m_paused)
  94.                         return s_completedTask;
  95.                     response = m_pauseResponse;
  96.                     resumeTask = m_resumeRequest.Task;
  97.                 }
  98.  
  99.                 response.TrySetResult(true);
  100.                 return resumeTask;
  101.             }
  102.  
  103.             public bool IsPaused
  104.             {
  105.                 get
  106.                 {
  107.                     lock (m_lockObject)
  108.                         return m_paused;
  109.                 }
  110.             }
  111.  
  112.             public PauseToken Token { get { return new PauseToken(this); } }
  113.         }
  114.  
  115.         public struct PauseToken
  116.         {
  117.             private readonly PauseTokenSource m_source;
  118.             public PauseToken(PauseTokenSource source) { m_source = source; }
  119.  
  120.             public bool IsPaused { get { return m_source != null && m_source.IsPaused; } }
  121.  
  122.             public Task WaitWhilePausedAsync()
  123.             {
  124.                 return IsPaused ?
  125.                         m_source.WaitWhilePausedAsync() :
  126.                         PauseTokenSource.s_completedTask;
  127.             }
  128.  
  129.             public Task WaitWhilePausedWithResponseAsyc()
  130.             {
  131.                 return IsPaused ?
  132.                         m_source.WaitWhilePausedWithResponseAsyc() :
  133.                         PauseTokenSource.s_completedTask;
  134.             }
  135.         }
  136.  
  137.         // Testing
  138.  
  139.         static async Task Test()
  140.         {
  141.             var pts = new PauseTokenSource();
  142.             var task = SomeMethodAsync(pts.Token);
  143.  
  144.             // sync version
  145.             Console.WriteLine("Before pause requested");
  146.             pts.PauseWithResponseAsync().Wait();
  147.             Console.WriteLine("After pause requested, paused: " + pts.Token.IsPaused);
  148.             pts.PauseWithResponseAsync().Wait();
  149.             Console.WriteLine("After pause requested, paused: " + pts.Token.IsPaused);
  150.             Console.WriteLine("Press enter to resume...");
  151.             Console.ReadLine();
  152.             pts.Resume();
  153.  
  154.             // async version:
  155.  
  156.             Console.WriteLine("Before pause requested");
  157.             await pts.PauseWithResponseAsync();
  158.             Console.WriteLine("After pause requested, paused: " + pts.Token.IsPaused);
  159.             await pts.PauseWithResponseAsync();
  160.             Console.WriteLine("After pause requested, paused: " + pts.Token.IsPaused);
  161.             Console.WriteLine("Press enter to resume...");
  162.             Console.ReadLine();
  163.             pts.Resume();
  164.  
  165.  
  166.             Console.WriteLine("Before pause requested");
  167.             pts.Pause();
  168.             Console.WriteLine("After pause requested, paused: " + pts.Token.IsPaused);
  169.             Console.WriteLine("Press enter to resume after the task has confirmed paused...");
  170.  
  171.  
  172.         }
  173.  
  174.         static void Main()
  175.         {
  176.             Test().Wait();
  177.             Console.WriteLine("Press enter to exit...");
  178.             Console.ReadLine();
  179.         }
  180.  
  181.         public static async Task SomeMethodAsync(PauseToken pause)
  182.         {
  183.             try
  184.             {
  185.                 while (true)
  186.                 {
  187.                     await Task.Delay(1000).ConfigureAwait(false);
  188.                     Console.WriteLine("Before await pause.WaitWhilePausedAsync()");
  189.                     await pause.WaitWhilePausedWithResponseAsyc();
  190.                     Console.WriteLine("After await pause.WaitWhilePausedAsync()");
  191.                 }
  192.             }
  193.             catch (Exception e)
  194.             {
  195.                 Console.WriteLine("Exception: {0}", e);
  196.                 throw;
  197.             }
  198.         }
  199.     }
  200. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement