异步task处理
Posted zeroone
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步task处理相关的知识,希望对你有一定的参考价值。
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; } } } }
以上是关于异步task处理的主要内容,如果未能解决你的问题,请参考以下文章