• 创建自己的awaitable类型


    在C# 5.0中引入了await关键字,通过它可以非常容易的实现异步操作。在大多数的时候,await一般适合Task一起使用的,也非常方便。但有的时候,我们也需要自定义我们自己的awaitable类型,以实现更高的灵活性和效率。

    可以用于await运算符的对象要求如下:

    1. 有一个GetAwaiter()方法或扩展方法,它返回一个实现了INotifyCompletion接口的awaiter对象(或结构)
    2. 返回的awaiter对象(或结构)要求实现如下方法:
    • void OnCompleted(Action continuation)
    • bool IsCompleted { get ; }
    • TResult GetResult() // TResult 也可以是 void 类型

    下面我就简单的介绍一下await运算符是如何实现异步操作的。

    例如,对于如下代码

        var j = await 3;
        DoContinue(j);

    在编译的时候会被编译器翻译为类似如下流程的代码(注:这个只是功能类似的简化流程示例,实际并非如此)。

        var awaiter = 3.GetAwaiter();
        var continuation = new Action(() =>
        {
            var j = awaiter.GetResult();
            DoContinue(j);
        });

        if (awaiter.IsCompleted)
            continuation();
        else
            awaiter.OnCompleted(continuation);

    有了这个基础,我们就可以对一个int型的变量实现await操作了:

        class Program
        {
            static void Main(string[] args)
            {
                Test();
                Console.ReadLine();
            }

            async static void Test()
            {
                var j = await 3;
                Console.WriteLine(j);
            }
        }

        class MyAwaiter : System.Runtime.CompilerServices.INotifyCompletion
        {
            public bool IsCompleted { get { return false; } }

            public void OnCompleted(Action continuation)
            {
                Console.WriteLine("OnCompleted");
                ThreadPool.QueueUserWorkItem(_ =>
                    {
                        Thread.Sleep(1000);
                        this.result = 300;
                        continuation();
                    });
            }

            int result;
            public int GetResult()
            {
                Console.WriteLine("GetResult");
                return result;
            }
        }

        static class Extend
        {
            public static MyAwaiter GetAwaiter(this int i)
            {
                return new MyAwaiter();
            }
        }

    这样我们就能看出await是如何实现call/cc式的异步操作了:

    1. 编译器把后续操作封装为一个Action对象continuation传入awaiter的OnCompleted函数并执行。
    2. awaiter在OnCompleted函数中执行异步操作,并在异步操作完成后(一般是异步调用的回调函数)执行continuation操作。
    3. continuation操作的第一步就是调用awaiter.GetResult()获取异步操作的返回值,并继续执行后续操作。

    看到这里,相信大家对await的机制已经有了简单的认识,也就不难理解为什么AsyncTargetingPack能使得.net 4.0程序也支持await操作了——该库在AsyncCompatLibExtensions类中对Task类提供了GetAwaiter扩展函数而已。

  • 相关阅读:
    android控件
    解决C#项目出现“此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 ..packagesMicrosoft.Net.Compilers.1.0.0uildMicrosoft.Net.Compilers.props”
    C#解密退款req_info结果通知
    解决C#中调用WCF方法报错:远程服务器返回错误 (404) 未找到
    解决网页出现 net::ERR_ABORTED 404 (Not Found)问题
    winform执行程序报错:已停止工作,windows正在检查该问题的解决方案
    C#操作数据表中XML格式的数据
    为了开篇
    iOS隐私政策
    在Android中调用KSOAP2库访问webservice服务出现的服务端传入参数为null的问题解决
  • 原文地址:https://www.cnblogs.com/TianFang/p/2696769.html
Copyright © 2020-2023  润新知