Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Transactions;
- namespace AsyncTest
- {
- /// <summary>Provides a SynchronizationContext that's single-threaded.</summary>
- public class SingleThreadSynchronizationContext : SynchronizationContext
- {
- /// <summary>The queue of work items.</summary>
- private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue =
- new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
- /// <summary>The processing thread.</summary>
- private readonly Thread m_thread = Thread.CurrentThread;
- /// <summary>Dispatches an asynchronous message to the synchronization context.</summary>
- /// <param name="d">The System.Threading.SendOrPostCallback delegate to call.</param>
- /// <param name="state">The object passed to the delegate.</param>
- public override void Post(SendOrPostCallback d, object state)
- {
- if (d == null) throw new ArgumentNullException("d");
- m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
- }
- /// <summary>Not supported.</summary>
- public override void Send(SendOrPostCallback d, object state)
- {
- throw new NotSupportedException("Synchronously sending is not supported.");
- }
- /// <summary>Runs an loop to process all queued work items.</summary>
- public void RunOnCurrentThread()
- {
- foreach (var workItem in m_queue.GetConsumingEnumerable())
- workItem.Key(workItem.Value);
- }
- /// <summary>Notifies the context that no more work will arrive.</summary>
- public void Complete() { m_queue.CompleteAdding(); }
- }
- class Program
- {
- public static void Run(Func<Task> func)
- {
- var prevCtx = SynchronizationContext.Current;
- try
- {
- var syncCtx = new SingleThreadSynchronizationContext();
- //var syncCtx = new System.Windows.Threading.DispatcherSynchronizationContext();
- SynchronizationContext.SetSynchronizationContext(syncCtx);
- var t = func();
- t.ContinueWith(
- delegate { syncCtx.Complete(); }, TaskScheduler.Default);
- syncCtx.RunOnCurrentThread();
- //var frame = new System.Windows.Threading.DispatcherFrame();
- //t.ContinueWith(_ => { frame.Continue = false; },
- // TaskScheduler.Default);
- //System.Windows.Threading.Dispatcher.PushFrame(frame);
- t.GetAwaiter().GetResult();
- }
- finally { SynchronizationContext.SetSynchronizationContext(prevCtx); }
- }
- static async Task TestStuff(int nb)
- {
- Console.WriteLine("Entering teststuff " + Thread.CurrentThread.ManagedThreadId);
- using (var scope = new TransactionScope())
- {
- int wait = 1000 + nb;
- await Task.Delay(wait);
- scope.Complete();
- }
- Console.WriteLine("Leaving teststuff " + Thread.CurrentThread.ManagedThreadId);
- }
- static void Main(string[] args)
- {
- Run(async delegate
- {
- var tasks = new Task[10];
- for (int i = 0; i < 10; i++)
- {
- tasks[i] = TestStuff(i);
- }
- await Task.WhenAll(tasks);
- });
- Console.ReadLine();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement