Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

await and transactionscope

By: a guest on Nov 24th, 2012  |  syntax: C#  |  size: 3.76 KB  |  views: 141  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Transactions;
  10.  
  11. namespace AsyncTest
  12. {
  13.     /// <summary>Provides a SynchronizationContext that's single-threaded.</summary>
  14.     public class SingleThreadSynchronizationContext : SynchronizationContext
  15.     {
  16.         /// <summary>The queue of work items.</summary>
  17.         private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue =
  18.             new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
  19.         /// <summary>The processing thread.</summary>
  20.         private readonly Thread m_thread = Thread.CurrentThread;
  21.  
  22.         /// <summary>Dispatches an asynchronous message to the synchronization context.</summary>
  23.         /// <param name="d">The System.Threading.SendOrPostCallback delegate to call.</param>
  24.         /// <param name="state">The object passed to the delegate.</param>
  25.         public override void Post(SendOrPostCallback d, object state)
  26.         {
  27.             if (d == null) throw new ArgumentNullException("d");
  28.             m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
  29.         }
  30.  
  31.         /// <summary>Not supported.</summary>
  32.         public override void Send(SendOrPostCallback d, object state)
  33.         {
  34.             throw new NotSupportedException("Synchronously sending is not supported.");
  35.         }
  36.  
  37.         /// <summary>Runs an loop to process all queued work items.</summary>
  38.         public void RunOnCurrentThread()
  39.         {
  40.             foreach (var workItem in m_queue.GetConsumingEnumerable())
  41.                 workItem.Key(workItem.Value);
  42.         }
  43.  
  44.         /// <summary>Notifies the context that no more work will arrive.</summary>
  45.         public void Complete() { m_queue.CompleteAdding(); }
  46.     }
  47.  
  48.     class Program
  49.     {
  50.         public static void Run(Func<Task> func)
  51.         {
  52.             var prevCtx = SynchronizationContext.Current;
  53.             try
  54.             {
  55.                 var syncCtx = new SingleThreadSynchronizationContext();
  56.                 //var syncCtx = new System.Windows.Threading.DispatcherSynchronizationContext();
  57.                 SynchronizationContext.SetSynchronizationContext(syncCtx);
  58.  
  59.                 var t = func();
  60.                 t.ContinueWith(
  61.                     delegate { syncCtx.Complete(); }, TaskScheduler.Default);
  62.  
  63.                 syncCtx.RunOnCurrentThread();
  64.                 //var frame = new System.Windows.Threading.DispatcherFrame();
  65.                 //t.ContinueWith(_ => { frame.Continue = false; },
  66.                 //    TaskScheduler.Default);
  67.                 //System.Windows.Threading.Dispatcher.PushFrame(frame);
  68.  
  69.                 t.GetAwaiter().GetResult();
  70.             }
  71.             finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
  72.         }
  73.  
  74.         static async Task TestStuff(int nb)
  75.         {
  76.             Console.WriteLine("Entering teststuff " + Thread.CurrentThread.ManagedThreadId);
  77.             using (var scope = new TransactionScope())
  78.             {
  79.                 int wait = 1000 + nb;
  80.                 await Task.Delay(wait);
  81.                 scope.Complete();
  82.             }
  83.            
  84.             Console.WriteLine("Leaving teststuff " + Thread.CurrentThread.ManagedThreadId);
  85.         }
  86.  
  87.         static void Main(string[] args)
  88.         {
  89.             Run(async delegate
  90.             {
  91.                 var tasks = new Task[10];
  92.                 for (int i = 0; i < 10; i++)
  93.                 {
  94.                     tasks[i] = TestStuff(i);
  95.                 }
  96.                 await Task.WhenAll(tasks);
  97.             });
  98.             Console.ReadLine();
  99.         }
  100.     }
  101. }