异步task处理
2016-03-06 09:37
417 查看
public async Task<Customers> GetCustomers() { return await Service.GetCustomersAsync(); }
public async void GetCustomers() { customerList = await GetCustomers(); }
引用方法 http://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously
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());
也可以使用如下方式:
.Net 4.5 下
// For Task<T>: will block until the task is completed... var result = task.Result; // For Task (not Task<T>): task2.RunSynchronously();
.Net 4.0 下
var x = (IAsyncResult)task; task.Start(); x.AsyncWaitHandle.WaitOne(); 或: task.Start(); task.Wait();
还有一个开源项目:https://github.com/tejacques/AsyncBridge/blob/master/src/AsyncBridge/AsyncHelper.cs
using System; using System.Collections.Concurrent; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace AsyncBridge { using EventTask = Tuple<SendOrPostCallback, object>; using EventQueue = ConcurrentQueue<Tuple<SendOrPostCallback, object>>; /// <summary> /// A Helper class to run Asynchronous functions from synchronous ones /// </summary> public static class AsyncHelper { /// <summary> /// A class to bridge synchronous asynchronous methods /// </summary> public class AsyncBridge : IDisposable { private ExclusiveSynchronizationContext CurrentContext; private SynchronizationContext OldContext; private int TaskCount; /// <summary> /// Constructs the AsyncBridge by capturing the current /// SynchronizationContext and replacing it with a new /// ExclusiveSynchronizationContext. /// </summary> internal AsyncBridge() { OldContext = SynchronizationContext.Current; CurrentContext = new ExclusiveSynchronizationContext(OldContext); SynchronizationContext .SetSynchronizationContext(CurrentContext); } /// <summary> /// Execute's an async task with a void return type /// from a synchronous context /// </summary> /// <param name="task">Task to execute</param> /// <param name="callback">Optional callback</param> public void Run(Task task, Action<Task> callback = null) { CurrentContext.Post(async _ => { try { Increment(); await task; if (null != callback) { callback(task); } } catch (Exception e) { CurrentContext.InnerException = e; } finally { Decrement(); } }, null); } /// <summary> /// Execute's an async task with a T return type /// from a synchronous context /// </summary> /// <typeparam name="T">The type of the task</typeparam> /// <param name="task">Task to execute</param> /// <param name="callback">Optional callback</param> public void Run<T>(Task<T> task, Action<Task<T>> callback = null) { if (null != callback) { Run((Task)task, (finishedTask) => callback((Task<T>)finishedTask)); } else { Run((Task)task); } } /// <summary> /// Execute's an async task with a T return type /// from a synchronous context /// </summary> /// <typeparam name="T">The type of the task</typeparam> /// <param name="task">Task to execute</param> /// <param name="callback"> /// The callback function that uses the result of the task /// </param> public void Run<T>(Task<T> task, Action<T> callback) { Run(task, (t) => callback(t.Result)); } private void Increment() { Interlocked.Increment(ref TaskCount); } private void Decrement() { Interlocked.Decrement(ref TaskCount); if (TaskCount == 0) { CurrentContext.EndMessageLoop(); } } /// <summary> /// Disposes the object /// </summary> public void Dispose() { try { CurrentContext.BeginMessageLoop(); } catch (Exception e) { throw e; } finally { SynchronizationContext .SetSynchronizationContext(OldContext); } } } /// <summary> /// Creates a new AsyncBridge. This should always be used in /// conjunction with the using statement, to ensure it is disposed /// </summary> public static AsyncBridge Wait { get { return new AsyncBridge(); } } /// <summary> /// Runs a task with the "Fire and Forget" pattern using Task.Run, /// and unwraps and handles exceptions /// </summary> /// <param name="task">A function that returns the task to run</param> /// <param name="handle">Error handling action, null by default</param> public static void FireAndForget( Func<Task> task, Action<Exception> handle = null) { #if NET_45 Task.Run( #elif NET_40 TaskEx.Run( #endif () => { ((Func<Task>)(async () => { try { await task(); } catch (Exception e) { if (null != handle) { handle(e); } } }))(); }); } private class ExclusiveSynchronizationContext : SynchronizationContext { private readonly AutoResetEvent _workItemsWaiting = new AutoResetEvent(false); private bool _done; private EventQueue _items; public Exception InnerException { get; set; } public ExclusiveSynchronizationContext(SynchronizationContext old) { ExclusiveSynchronizationContext oldEx = old as ExclusiveSynchronizationContext; if (null != oldEx) { this._items = oldEx._items; } else { this._items = new EventQueue(); } } 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) { _items.Enqueue(Tuple.Create(d, state)); _workItemsWaiting.Set(); } public void EndMessageLoop() { Post(_ => _done = true, null); } public void BeginMessageLoop() { while (!_done) { EventTask task = null; if (!_items.TryDequeue(out task)) { task = null; } if (task != null) { task.Item1(task.Item2); if (InnerException != null) // method threw an exeption { throw new AggregateException( "AsyncBridge.Run method threw an exception.", InnerException); } } else { _workItemsWaiting.WaitOne(); } } } public override SynchronizationContext CreateCopy() { return this; } } } }
相关文章推荐
- 在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
- codeforcces 623A - Graph and String Note that 构造
- SVN 取消版本控制并添加至忽略列表
- 全文检索(二)-基于lucene4.10的增删改查
- Android应用程序打包时,出现错误:"XXX" is not translated in "af" , "am" , "ar" ....
- hdu oj 1062 Text Reverse(字符串)
- 51nod 1089 最长回文字串V2(Manacher算法)
- 机器学习经典算法logistic回归
- WINCE快捷方式详解
- jsr303 参考表
- 延迟X秒之后执行某个方法
- Code Recyclebin Contact me QQ:149906878 Write operations are not allowed in read-only mode (FlushMo
- 2016.3.5 14.6复习篇之二(蓝桥杯快速恶补)
- 最长回文串manacher算法模板
- TCPIP编程
- vector作二维数组应用
- 把Java数组转换为List时的注意事项
- Ettercap中间人攻击--介绍
- Codeforces 622F 「数学数论」「数学规律」
- iOS应用中使用Auto Layout实现自定义cell及拖动回弹