zoukankan      html  css  js  c++  java
  • 实现一个可以用 await 异步等待的 Awaiter

    总结起来,要想使一个方法可被 await 等待,必须具备以下条件:

    这个方法返回一个类 A 的实例,这个类 A 必须满足后面的条件。
    此类 A 有一个可被访问到的 GetAwaiter 方法(扩展方法也行,这算是黑科技吗?),方法返回类 B 的实例,这个类 B 必须满足后面的条件;
    此类 B 实现 INotifyCompletion 接口,且拥有 bool IsCompleted { get; } 属性、GetResult() 方法、void OnCompleted(Action continuation) 方法。
    https://blog.csdn.net/WPwalter/article/details/78387736

    using System.Runtime.CompilerServices;
    
    namespace Walterlv.Threading
    {
        /// <summary>
        /// 表示一个可等待对象,如果一个方法返回此类型的实例,则此方法可以使用 `await` 异步等待。
        /// </summary>
        /// <typeparam name="TAwaiter">用于给 await 确定返回时机的 IAwaiter 的实例。</typeparam>
        public interface IAwaitable<out TAwaiter> where TAwaiter : IAwaiter
        {
            /// <summary>
            /// 获取一个可用于 await 关键字异步等待的异步等待对象。
            /// 此方法会被编译器自动调用。
            /// </summary>
            TAwaiter GetAwaiter();
        }
    
        /// <summary>
        /// 表示一个包含返回值的可等待对象,如果一个方法返回此类型的实例,则此方法可以使用 `await` 异步等待返回值。
        /// </summary>
        /// <typeparam name="TAwaiter">用于给 await 确定返回时机的 IAwaiter{<typeparamref name="TResult"/>} 的实例。</typeparam>
        /// <typeparam name="TResult">异步返回的返回值类型。</typeparam>
        public interface IAwaitable<out TAwaiter, out TResult> where TAwaiter : IAwaiter<TResult>
        {
            /// <summary>
            /// 获取一个可用于 await 关键字异步等待的异步等待对象。
            /// 此方法会被编译器自动调用。
            /// </summary>
            TAwaiter GetAwaiter();
        }
    
        /// <summary>
        /// 用于给 await 确定异步返回的时机。
        /// </summary>
        public interface IAwaiter : INotifyCompletion
        {
            /// <summary>
            /// 获取一个状态,该状态表示正在异步等待的操作已经完成(成功完成或发生了异常);此状态会被编译器自动调用。
            /// 在实现中,为了达到各种效果,可以灵活应用其值:可以始终为 true,或者始终为 false。
            /// </summary>
            bool IsCompleted { get; }
    
            /// <summary>
            /// 此方法会被编译器在 await 结束时自动调用以获取返回状态(包括异常)。
            /// </summary>
            void GetResult();
        }
    
        /// <summary>
        /// 当执行关键代码(此代码中的错误可能给应用程序中的其他状态造成负面影响)时,
        /// 用于给 await 确定异步返回的时机。
        /// </summary>
        public interface ICriticalAwaiter : IAwaiter, ICriticalNotifyCompletion
        {
        }
    
        /// <summary>
        /// 用于给 await 确定异步返回的时机,并获取到返回值。
        /// </summary>
        /// <typeparam name="TResult">异步返回的返回值类型。</typeparam>
        public interface IAwaiter<out TResult> : INotifyCompletion
        {
            /// <summary>
            /// 获取一个状态,该状态表示正在异步等待的操作已经完成(成功完成或发生了异常);此状态会被编译器自动调用。
            /// 在实现中,为了达到各种效果,可以灵活应用其值:可以始终为 true,或者始终为 false。
            /// </summary>
            bool IsCompleted { get; }
    
            /// <summary>
            /// 获取此异步等待操作的返回值,此方法会被编译器在 await 结束时自动调用以获取返回值(包括异常)。
            /// </summary>
            /// <returns>异步操作的返回值。</returns>
            TResult GetResult();
        }
    
        /// <summary>
        /// 当执行关键代码(此代码中的错误可能给应用程序中的其他状态造成负面影响)时,
        /// 用于给 await 确定异步返回的时机,并获取到返回值。
        /// </summary>
        /// <typeparam name="TResult">异步返回的返回值类型。</typeparam>
        public interface ICriticalAwaiter<out TResult> : IAwaiter<TResult>, ICriticalNotifyCompletion
        {
        }
    }
    

      

     https://stackoverflow.com/questions/19535147/await-and-synchronizationcontext-in-a-managed-component-hosted-by-an-unmanaged-a/19555959#19555959

    public class ContextAwaiter<T> : INotifyCompletion
        {
            readonly Control _control;
            readonly TaskAwaiter<T> _awaiter;
            readonly bool _alwaysAsync;
    
            public ContextAwaiter(Task<T> task, Control control, bool alwaysAsync)
            {
                _awaiter = task.GetAwaiter();
                _control = control;
                _alwaysAsync = alwaysAsync;
            }
    
            public ContextAwaiter<T> GetAwaiter() { return this; }
    
            public bool IsCompleted { get { return !_alwaysAsync && _awaiter.IsCompleted; } }
    
            public void OnCompleted(Action continuation)
            {
                if (_alwaysAsync || _control.InvokeRequired)
                {
                    Action<Action> callback = (c) => _awaiter.OnCompleted(c);
                    _control.BeginInvoke(callback, continuation);
                }
                else
                    _awaiter.OnCompleted(continuation);
            }
    
            public T GetResult()
            {
                return _awaiter.GetResult();
            }
        }
    }
    

      

  • 相关阅读:
    Ext JS 6应用程序Build后出现“c is not a constructor return new c(a[0])”的处理
    安卓四大组件总览
    摆脱命令行,Ubuntu下配置Android开发环境
    【翻译】使用Sencha Ext JS创建美丽的图画(1)
    linux后台运行springboot项目
    AES地址栏传参加密
    最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
    阿里云服务器+ftp文件操作+基于Centos7的vsftpd配置
    解决服务器发回了不可路由的地址。使用服务器地址代替的问题
    解决vsftpd的refusing to run with writable root inside chroot错误
  • 原文地址:https://www.cnblogs.com/Charltsing/p/awaiter.html
Copyright © 2011-2022 走看看