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();
            }
        }
    }
    

      

  • 相关阅读:
    yocto添加源码并编译进文件系统
    yocto编译加速及单独编译内核与uboot
    mysql 创建索引
    redis初使用
    mysql修改时区
    linux修改时间
    服务器环境配置安装(mysql+redis+nodejs+nginx)
    由于找不到MSVCP20.dll,无法继续执行代码
    sequelize初使用
    css flex
  • 原文地址:https://www.cnblogs.com/Charltsing/p/awaiter.html
Copyright © 2011-2022 走看看