zoukankan      html  css  js  c++  java
  • 自己实现async和await

      无意当中看了一些博文,说有人想自己尝试实现基于异步操作的方法:

      1)直接使用Task(不说咯,这个是微软给我们的标准实现方法)。

      2)必须继承INotifyCompletion接口,同时自己实现IsCompleted(必须)和Result(可选),GetResult(必须)OnCompleted(必须)方法:

      下面是一个具体的例子(自实现异步函数): 

    public interface IAwait<out T> : INotifyCompletion
        {
            bool IsCompleted { get; }
            T Result { get; }
            T GetResult();
        }
        public interface IAwaitable<out T>
        {
            IAwait<T> GetAwaiter();
        }
    
        public class AwaitableFunc<T> : IAwaitable<T>
        {
            private Func<T> fun = null;
    
            public IAwait<T> GetAwaiter()
            {
                return new InnerAwaitableImplement(fun);
            }
    
            public AwaitableFunc(Func<T> func)
            {
                fun = func;
            }
    
            private class InnerAwaitableImplement : IAwait<T>
            {
                private Func<T> fun = null;
                private bool isFinished=false;
                private T result = default(T);
    
                public InnerAwaitableImplement(Func<T> func)
                {
                    fun = func;
                }
                public bool IsCompleted
                {
                    get
                    {
                        return isFinished;
                    }
                }
    
                public T Result
                {
                    get
                    {
                        return GetResult();
                    }
                }
    
                public void OnCompleted(Action continuation)
                {
                    ThreadPool.QueueUserWorkItem(obj => 
                    {
                        isFinished = true;
                        continuation();
                    }, null);
                }
    
    
                public T GetResult()
                {
                    result = fun();
                    return result;
                }
            }
        }

    GetResult和Result属性应该实现同步的方法(阻塞线程的),OnCompleted实现异步方法(必须新线程去处理)。这样的话,一旦主程序这样调用:

    AwaitableFunc<int> afunc = new AwaitableFunc<int>(() =>
                {
                    //模拟一个长时间的任务,注意这里如果用同步机器就死掉
                    Thread.Sleep(5000);
                    return 1;
                });
    
                var result =  afunc.GetAwaiter();
    
                result.OnCompleted(() =>
                {
                    MessageBox.Show(result.GetResult().ToString());
                });

    你会发现,GetAwaiter方法会先被执行,判断IsCompleted是否为false,如果是false,先执行OnCompleted的方法(作为回调函数一样的性质)先保留,然后开辟新线程执行GetResult(),最后回调到OnCompleted执行回调函数。

    你也可以这样调用:

    private  async void button1_Click(object sender, EventArgs e)
            {
                AwaitableFunc<int> afunc = new AwaitableFunc<int>(() =>
                {
                    //模拟一个长时间的任务,注意这里如果用同步机器就死掉
                    Thread.Sleep(5000);
                    return 1;
                });
    
                var result = await afunc;
                MessageBox.Show(result.ToString());
            }

    类似于第一个示例(这里就指出了await其实本质是一个回调函数,编译器自动把await下面的东西全部包含到里边去了,简单叙述原理,注意代码中红色标示部分的位置!)。

    其实,GetResult并不是一定需要的,比如这个对int任意进行延时(不直接调用Task.Delay方法,自己写一个呗):

    public class TimeDelay
        {
            private int _delayTime = 0;
    
            public TimeDelay(int delayNumber)
            {
                _delayTime = delayNumber;
            }
            public InnerAwaitableImplement GetAwaiter()
            {
                return new InnerAwaitableImplement(_delayTime);
            }
            public class InnerAwaitableImplement:INotifyCompletion
            {
                private int _delayTime = 0;
                private bool isFinished=false;
    
                public InnerAwaitableImplement(int delayTime)
                {
                    _delayTime = delayTime;
                }
                public bool IsCompleted
                {
                    get
                    {
                        return isFinished;
                    }
                }
                public void OnCompleted(Action continuation)
                {
                    ThreadPool.QueueUserWorkItem(obj => 
                    {
                        Thread.Sleep(_delayTime);
                        isFinished = true;
                        continuation();
                    }, null);
                }
    
    
                public void GetResult()
                {
                    
                }
            }
        }

    这样使用:

    private async void button1_Click(object sender, EventArgs e)
            {
                TimeDelay afunc = new TimeDelay(2500);
                await afunc;
                MessageBox.Show("OK");
            }

    更简单地——扩展方法:

    public class TimeDelay
        {
            private int _delayTime = 0;
    
            public TimeDelay(int delayNumber)
            {
                _delayTime = delayNumber;
            }
            public InnerAwaitableImplement GetAwaiter()
            {
                return new InnerAwaitableImplement(_delayTime);
            }
            public class InnerAwaitableImplement:INotifyCompletion
            {
                private int _delayTime = 0;
                private bool isFinished=false;
    
                public InnerAwaitableImplement(int delayTime)
                {
                    _delayTime = delayTime;
                }
                public bool IsCompleted
                {
                    get
                    {
                        return isFinished;
                    }
                }
                public void OnCompleted(Action continuation)
                {
                    ThreadPool.QueueUserWorkItem(obj => 
                    {
                        Thread.Sleep(_delayTime);
                        isFinished = true;
                        continuation();
                    }, null);
                }
    
    
                public void GetResult()
                {
                    
                }
            }
        }
    
        public static class IntExtend
        {
            public static TimeDelay.InnerAwaitableImplement GetAwaiter(this int delayTime)
            {
                TimeDelay td = new TimeDelay(delayTime);
                return td.GetAwaiter();
            }
        }

    这样调用:

    private async void button1_Click(object sender, EventArgs e)
            {await 1000;
                MessageBox.Show("OK");
            }
  • 相关阅读:
    git提交代码
    python把&#DDDDDD转换为中文
    mac下载安装airtest
    mac安装指定版本的python
    python操作habse
    pyspark操作数据库
    Scrapy_redis爬虫项目
    python实现对列表元素是字典的排序
    postman使用
    图书推荐
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/3917696.html
Copyright © 2011-2022 走看看