同步调用异步方法how-would-i-run-an-async-taskt-method-synchronously
2018-02-05 19:31
483 查看
同步调用异步方法帮助类:
public static class AsyncHelpers { /// <summary> /// Execute's an async Task<T> method which has a void return value synchronously /// </summary> /// <param name="task">Task<T> method to execute</param> public static void RunSync(Func<Task> task) { var oldContext = SynchronizationContext.Current; var synch = new ExclusiveSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(synch); synch.Post(async _ => { try { await task(); } catch (Exception e) { synch.InnerException = e; throw; } finally { synch.EndMessageLoop(); } }, null); synch.BeginMessageLoop(); SynchronizationContext.SetSynchronizationContext(oldContext); } /// <summary> /// Execute's an async Task<T> method which has a T return type synchronously /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="task">Task<T> method to execute</param> /// <returns></returns> public 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; } } }
使用
customerList = AsyncHelpers.RunSync<List<Customer>>(() => GetCustomers());
来源链接
http://social.msdn.microsoft.com/Forums/en/async/thread/163ef755-ff7b-4ea5-b226-bbe8ef5f4796相关文章推荐
- async await 同步方法调用异步方法死锁
- 水火难容:同步方法调用async方法引发的ASP.NET应用程序崩溃
- 用异步的方式调用同步方法
- C#的新特性体验(异步方法的同步调用)
- Spring源码学习之:@Async 方法上添加该注解实现异步调用的原理
- C#~异步编程再续~async异步方法与同步方法的并行
- C#的同步和异步调用方法
- VC++ .NET UI同步(使用Invoke托管方法),异步线程调用UI
- C#的新特性体验(异步方法的同步调用)
- 在同步中调用异步方法[.net 4.5]
- WCF分布式开发常见错误(13):The transaction under which this method call was executing ,此方法调用的事务被异步中断
- Silverlight调用WCF方法时异步转同步Synchronous Web Service Calls with Silverlight: Dispelling the async-only myth
- 使用异步方式调用同步方法
- .NET 4.5 使用async和await关键字调用异步方法
- 利用AsyncCallback将同步方法转为异步执行
- Spring中@Async注解实现方法的异步调用
- .NET/C# 使用async和await关键字调用异步方法
- 在同步方法中调用异步方法时如何避免死锁问题
- 多线程陷阱(不要调用run方法;静态的同步方法)
- 使用异步方式调用同步方法