博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
创建自己的awaitable类型
阅读量:6277 次
发布时间:2019-06-22

本文共 1705 字,大约阅读时间需要 5 分钟。

在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扩展函数而已。

转载地址:http://xbyva.baihongyu.com/

你可能感兴趣的文章
第23章 访问者模式(Visitor Pattern)
查看>>
第21章 策略模式(Strategy Pattern)
查看>>
Python基础(7)--函数
查看>>
用jQuery.ajaxWebService请求WebMethod,Ajax处理实现局部刷新;及Jquery传参数,并跳转页面 用post传过长参数...
查看>>
PHP虚拟主机的配置
查看>>
C语言函数调用栈(二)
查看>>
HTTP Keep-Alive详解
查看>>
Data URI scheme - 数据的uri模式
查看>>
搜索引擎原理
查看>>
java良好的编码习惯
查看>>
利用JasperReport+iReport进行Web报表开发
查看>>
C# 获取与解析枚举类型的 DescriptionAttribute
查看>>
WPF之Binding深入探讨
查看>>
HDU 4333 Revolving Digits 扩展KMP
查看>>
Spark JDBC入门测试
查看>>
AMD and CMD are dead之KMDjs内核之分号
查看>>
数据库SQL优化大总结之 百万级数据库优化方案
查看>>
手把手教你写专利申请书/怎样申请专利
查看>>
MVC - 12.HtmlHelper
查看>>
反调试技术揭秘
查看>>