Created
March 7, 2019 13:59
-
-
Save Mark-Broadhurst/8a00ef85a46216f46e6743a4449a2d42 to your computer and use it in GitHub Desktop.
RunAsync
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private static T RunSync<T>(Func<Task<T>> task) | |
{ | |
var oldContext = SynchronizationContext.Current; | |
var synch = new ExclusiveSynchronizationContext(); | |
SynchronizationContext.SetSynchronizationContext(synch); | |
T ret = default(T); | |
synch.Post(async _ => | |
{ | |
try | |
{ | |
ret = await task(); | |
} | |
catch (Exception e) | |
{ | |
synch.InnerException = e; | |
throw; | |
} | |
finally | |
{ | |
synch.EndMessageLoop(); | |
} | |
}, null); | |
synch.BeginMessageLoop(); | |
SynchronizationContext.SetSynchronizationContext(oldContext); | |
return ret; | |
} | |
private class ExclusiveSynchronizationContext : SynchronizationContext | |
{ | |
private bool done; | |
public Exception InnerException { get; set; } | |
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); | |
readonly Queue<Tuple<SendOrPostCallback, object>> items = | |
new Queue<Tuple<SendOrPostCallback, object>>(); | |
public override void Send(SendOrPostCallback d, object state) | |
{ | |
throw new NotSupportedException("We cannot send to our same thread"); | |
} | |
public override void Post(SendOrPostCallback d, object state) | |
{ | |
lock (items) | |
{ | |
items.Enqueue(Tuple.Create(d, state)); | |
} | |
workItemsWaiting.Set(); | |
} | |
public void EndMessageLoop() | |
{ | |
Post(_ => done = true, null); | |
} | |
public void BeginMessageLoop() | |
{ | |
while (!done) | |
{ | |
Tuple<SendOrPostCallback, object> task = null; | |
lock (items) | |
{ | |
if (items.Count > 0) | |
{ | |
task = items.Dequeue(); | |
} | |
} | |
if (task != null) | |
{ | |
task.Item1(task.Item2); | |
if (InnerException != null) // the method threw an exeption | |
{ | |
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException); | |
} | |
} | |
else | |
{ | |
workItemsWaiting.WaitOne(); | |
} | |
} | |
} | |
public override SynchronizationContext CreateCopy() | |
{ | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment