Advertisement
ivandrofly

Async Task<T> method synchronously?

Apr 26th, 2015
504
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.81 KB | None | 0 0
  1. public static class AsyncHelpers
  2. {
  3.     /// <summary>
  4.     /// Execute's an async Task<T> method which has a void return value synchronously
  5.     /// </summary>
  6.     /// <param name="task">Task<T> method to execute</param>
  7.     public static void RunSync(Func<Task> task)
  8.     {
  9.         var oldContext = SynchronizationContext.Current;
  10.         var synch = new ExclusiveSynchronizationContext();
  11.         SynchronizationContext.SetSynchronizationContext(synch);
  12.         synch.Post(async _ =>
  13.         {
  14.             try
  15.             {
  16.                 await task();
  17.             }
  18.             catch (Exception e)
  19.             {
  20.                 synch.InnerException = e;
  21.                 throw;
  22.             }
  23.             finally
  24.             {
  25.                 synch.EndMessageLoop();
  26.             }
  27.         }, null);
  28.         synch.BeginMessageLoop();
  29.  
  30.         SynchronizationContext.SetSynchronizationContext(oldContext);
  31.     }
  32.  
  33.     /// <summary>
  34.     /// Execute's an async Task<T> method which has a T return type synchronously
  35.     /// </summary>
  36.     /// <typeparam name="T">Return Type</typeparam>
  37.     /// <param name="task">Task<T> method to execute</param>
  38.     /// <returns></returns>
  39.     public static T RunSync<T>(Func<Task<T>> task)
  40.     {
  41.         var oldContext = SynchronizationContext.Current;
  42.         var synch = new ExclusiveSynchronizationContext();
  43.         SynchronizationContext.SetSynchronizationContext(synch);
  44.         T ret = default(T);
  45.         synch.Post(async _ =>
  46.         {
  47.             try
  48.             {
  49.                 ret = await task();
  50.             }
  51.             catch (Exception e)
  52.             {
  53.                 synch.InnerException = e;
  54.                 throw;
  55.             }
  56.             finally
  57.             {
  58.                 synch.EndMessageLoop();
  59.             }
  60.         }, null);
  61.         synch.BeginMessageLoop();
  62.         SynchronizationContext.SetSynchronizationContext(oldContext);
  63.         return ret;
  64.     }
  65.  
  66.     private class ExclusiveSynchronizationContext : SynchronizationContext
  67.     {
  68.         private bool done;
  69.         public Exception InnerException { get; set; }
  70.         readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
  71.         readonly Queue<Tuple<SendOrPostCallback, object>> items =
  72.             new Queue<Tuple<SendOrPostCallback, object>>();
  73.  
  74.         public override void Send(SendOrPostCallback d, object state)
  75.         {
  76.             throw new NotSupportedException("We cannot send to our same thread");
  77.         }
  78.  
  79.         public override void Post(SendOrPostCallback d, object state)
  80.         {
  81.             lock (items)
  82.             {
  83.                 items.Enqueue(Tuple.Create(d, state));
  84.             }
  85.             workItemsWaiting.Set();
  86.         }
  87.  
  88.         public void EndMessageLoop()
  89.         {
  90.             Post(_ => done = true, null);
  91.         }
  92.  
  93.         public void BeginMessageLoop()
  94.         {
  95.             while (!done)
  96.             {
  97.                 Tuple<SendOrPostCallback, object> task = null;
  98.                 lock (items)
  99.                 {
  100.                     if (items.Count > 0)
  101.                     {
  102.                         task = items.Dequeue();
  103.                     }
  104.                 }
  105.                 if (task != null)
  106.                 {
  107.                     task.Item1(task.Item2);
  108.                     if (InnerException != null) // the method threw an exeption
  109.                     {
  110.                         throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
  111.                     }
  112.                 }
  113.                 else
  114.                 {
  115.                     workItemsWaiting.WaitOne();
  116.                 }
  117.             }
  118.         }
  119.  
  120.         public override SynchronizationContext CreateCopy()
  121.         {
  122.             return this;
  123.         }
  124.     }
  125. }
  126. // Found in: http://ivandrofly/mjkhxx
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement