您的位置:首页 > 其它

异步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;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: