Advertisement
Noseratio

SO-19613444-2

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