C#多线程编程笔记(5.1)-使用await操作符获取异步任务结果

近来在学习Eugene Agafonov编写的《C#多线程编程实战》(译),做些笔记也顺便分享一下^-^

本例将讲述使用异步函数的基本场景,比较使用TPL和使用await操作符获取异步操作结果的不同之处。

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Dynamic;
using System.Runtime.CompilerServices;
using ImpromptuInterface;

namespace 对动态类型使用await
{
    class Program
    {
        static void Main(string[] args)
        {
            Task t = AsynchronousProcessing();
            t.Wait();

            Console.ReadKey();
        }

        public interface IAwaiter<T> : INotifyCompletion
        {
            bool IsCompleted { get; }

            T GetResult();
        }

        static string GetInfo()
        {
            return string.Format("Task is running on a thread id {0}.Is thread pool thread: {1}",
                Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }

        static dynamic GetDynamicAwaitableObject(bool completeSynchronously)
        {
            dynamic result = new ExpandoObject();
            dynamic awaiter = new ExpandoObject();

            awaiter.Message = "Completed synchronously";
            awaiter.IsCompleted = completeSynchronously;
            awaiter.GetResult = (Func<string>)(() => awaiter.Message);

            awaiter.OnCompleted = (Action<Action>)(callback =>
            {
                ThreadPool.QueueUserWorkItem(state =>
                {
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                    awaiter.Message = GetInfo();
                    if (callback != null)
                    {
                        callback();
                    }
                });
            });

            IAwaiter<string> proxy = Impromptu.ActLike(awaiter);

            result.GetAwaiter = (Func<dynamic>)(() => proxy);

            return result;
        }

        async static Task AsynchronousProcessing()
        {
            string result = await GetDynamicAwaitableObject(true);
            Console.WriteLine(result);

            result = await GetDynamicAwaitableObject(false);
            Console.WriteLine(result);
        }
    }
}

程序运行结果如下


当程序运行时运行了两个异步操作。其中一个是标准的TPL模式的代码,第二个使用了C#的新特性async和await。AsynchronyWithTPL方法启动了一个任务,运行两秒后返回关于工作线程信息的字符串。然后我们定义了一个后续操作,用于在异步操作完成后打印出该操作结果,还有另一个后续操作,用于万一有错误发生时打印出异常的细节。最终,返回了一个代表其中一个后续操作任务的任务,并等待其在Main函数中完成。

在AsynchronyWithAwait方法中,我们对任务使用await并得到了相同的结果。这和编写通常的同步代码的风格一样,即我们获取任务的结果,打印出结果,如果任务完成时带有错误则捕获异常。关键不同的是这实际上是一个异步程序。使用await后,C#立即创建了一个任务,其有一个后续操作任务,包含了await操作符后面的所有剩余代码。这个新任务也处理了异常传播。然后,将该任务返回到主方法中并等待其完成。


猜你喜欢

转载自blog.csdn.net/qq_35445058/article/details/80853239