Debug.WriteLine(Thread.CurrentThread.ManagedThreadId); await Task.Run(() => Debug.WriteLine(Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
class CustomSynchronizationContext : SynchronizationContext, IDisposable { private readonly AutoResetEvent _eventReset; private readonly Queue<KeyValuePair<SendOrPostCallback, object>> _workItems; private readonly Thread _thread; public CustomSynchronizationContext() { _eventReset = new AutoResetEvent(false); _workItems = new Queue<KeyValuePair<SendOrPostCallback, object>>(); _thread = new Thread(DoWork); _thread.Start(this); } private void DoWork(object obj) { SynchronizationContext.SetSynchronizationContext(obj as SynchronizationContext); while (true) { while (_workItems.Count > 0) { var item = _workItems.Dequeue(); item.Key(item.Value); } _eventReset.Reset(); _eventReset.WaitOne(); } } public override void Post(SendOrPostCallback d, object state) { _workItems.Enqueue(new KeyValuePair<SendOrPostCallback, object>(d, state)); _eventReset.Set(); } public void Dispose() { _eventReset.Dispose(); _thread.Abort(); } }
static void Main(string[] args) { var syncContext = new CustomSynchronizationContext(); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); syncContext.Post(o => Console.WriteLine(Thread.CurrentThread.ManagedThreadId), null); }
static void Main(string[] args) { using (var syncContext = new CustomSynchronizationContext()) { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); syncContext.Post(o => Console.WriteLine(Thread.CurrentThread.ManagedThreadId), null); } }
static void Main(string[] args) { var syncContext = new CustomSynchronizationContext(); try { syncContext.Post(o => { throw new Exception("TestException"); }, null); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
class CustomSynchronizationContext : SynchronizationContext, IDisposable { private readonly AutoResetEvent _workerResetEvent; private readonly ConcurrentQueue<WorkItem> _workItems; private readonly Thread _thread; public CustomSynchronizationContext() { _workerResetEvent = new AutoResetEvent(false); _workItems = new ConcurrentQueue<WorkItem>(); _thread = new Thread(DoWork); _thread.Start(this); } private void DoWork(object obj) { SynchronizationContext.SetSynchronizationContext(obj as SynchronizationContext); while (true) { WorkItem workItem; while (_workItems.TryDequeue(out workItem)) workItem.Execute(); //Note: race condition here _workerResetEvent.Reset(); _workerResetEvent.WaitOne(); } } public override void Send(SendOrPostCallback d, object state) { if (Thread.CurrentThread == _thread) d(state); else { using (var resetEvent = new AutoResetEvent(false)) { var wiExecutionInfo = new WorkItemExecutionInfo(); _workItems.Enqueue(new SynchronousWorkItem(d, state, resetEvent, ref wiExecutionInfo)); _workerResetEvent.Set(); resetEvent.WaitOne(); if (wiExecutionInfo.HasException) throw wiExecutionInfo.Exception; } } } public override void Post(SendOrPostCallback d, object state) { _workItems.Enqueue(new AsynchronousWorkItem(d, state)); _workerResetEvent.Set(); } public void Dispose() { _workerResetEvent.Dispose(); _thread.Abort(); } private class WorkItemExecutionInfo { public bool HasException => Exception != null; public Exception Exception { get; set; } } private abstract class WorkItem { protected readonly SendOrPostCallback SendOrPostCallback; protected readonly object State; protected WorkItem(SendOrPostCallback sendOrPostCallback, object state) { SendOrPostCallback = sendOrPostCallback; State = state; } public abstract void Execute(); } private class SynchronousWorkItem : WorkItem { private readonly AutoResetEvent _syncObject; private readonly WorkItemExecutionInfo _workItemExecutionInfo; public SynchronousWorkItem(SendOrPostCallback sendOrPostCallback, object state, AutoResetEvent resetEvent, ref WorkItemExecutionInfo workItemExecutionInfo) : base(sendOrPostCallback, state) { if (workItemExecutionInfo == null) throw new NullReferenceException(nameof(workItemExecutionInfo)); _syncObject = resetEvent; _workItemExecutionInfo = workItemExecutionInfo; } public override void Execute() { try { SendOrPostCallback(State); } catch (Exception ex) { _workItemExecutionInfo.Exception = ex; } _syncObject.Set(); } } private class AsynchronousWorkItem : WorkItem { public AsynchronousWorkItem(SendOrPostCallback sendOrPostCallback, object state) : base(sendOrPostCallback, state) { } public override void Execute() { SendOrPostCallback(State); } } }
static void Main(string[] args) { var syncContext = new CustomSynchronizationContext(); try { syncContext.Send(o => { throw new Exception("TestException"); }, null); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
static void Main(string[] args) { var syncContext = new CustomSynchronizationContext(); syncContext.Post(TestAsyncMethod, null); } async static void TestAsyncMethod(object obj) { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); await Task.Run(() => Console.WriteLine(Thread.CurrentThread.ManagedThreadId)); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); }
Source: https://habr.com/ru/post/269985/
All Articles