zoukankan      html  css  js  c++  java
  • 异步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;
                }
            }
        }
    }
  • 相关阅读:
    分页存储过程
    WinForm中DataGridView显示更新数据--人性版
    char类型的说明
    代码创建数据库_表--SqlServer数据库
    单例设计模式
    c#中的正则表达式
    sessionStorage 和 localStorage
    图片懒加载插件lazyload.js详解
    git安装加操作(转)
    php获取数据转换成json格式
  • 原文地址:https://www.cnblogs.com/zeroone/p/5246572.html
Copyright © 2011-2022 走看看