zoukankan      html  css  js  c++  java
  • 创建自己的awaitable类型

    From: http://www.cnblogs.com/TianFang/archive/2012/09/21/2696769.html

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

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

    1. 有一个GetAwaiter()方法或扩展方法,它返回一个实现了INotifyCompletion接口的awaiter对象(或结构)
    2. 返回的awaiter对象(或结构)要求实现如下方法:
    • void OnCompleted(Action continuation)
    • bool IsCompleted {get; }
    • TResultGetResult()// 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
    {
      staticvoid 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 {returnfalse; } }

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



    using System;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                DoSomething();
            }
    
            public async Task DoSomething()
            {
                int test = 3;
                await Sleep();
                MessageBox.Show("Woke up!" + test.ToString());
            }
    
            internal MyTask Sleep()
            {
                return new MyTask();
            }
    
            public class MyTask
            {
                public MyAwaiter GetAwaiter()
                {
                    return new MyAwaiter(); 
                }
            }
    
            public class MyAwaiter : INotifyCompletion
            {
                public MyAwaiter()
                {
                }
    
                public void OnCompleted(Action continuation)
                {
                    new Thread(() =>
                    {
                        Thread.Sleep(3000);
                        continuation();
                    }
                    ).Start();
                }
    
                public bool IsCompleted
                {
                    get
                    {
                        return false;
                    }
                }
    
                public void GetResult()
                {
                }
            }
    
    
        }
    }

    C#会把MessageBox.Show封装成continuation()传给OnComplete()函数。

  • 相关阅读:
    HNCU 1746: 算法4-1,4-3:定位子串
    HNCU 1330: 算法3-1:八进制数
    HNCU 1741: 算法3-2:行编辑程序
    51NOD 1073 约瑟夫环
    约瑟夫问题
    HNCU1325: 算法2-3~2-6:Big Bang(静态链表)
    指针知识复习
    html----学完总结
    html7---转载---为何img,input等内联元素可以设置高度与宽度
    html6---转载---块级元素与行内元素
  • 原文地址:https://www.cnblogs.com/puncha/p/3877019.html
Copyright © 2011-2022 走看看