Skip to content

C# 多线程 05-使用 C#6.0 09-对动态类型使用 await

🏷️ 《C# 多线程》

实现的功能同 05-使用 C#6.0 08-自定义 awaitable 类型 是一样的,只是这里是使用动态类型实现的。

注意

本例需要导入 ImpromptuInterface

示例代码

csharp
using ImpromptuInterface;
using System;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace Recipe5_9
{
    class Program
    {
        /// <summary>
        /// 对动态类型使用 await
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Task t = AsynchronousProcessing();
            t.Wait();

            Console.ReadLine();
        }

        static async Task AsynchronousProcessing()
        {
            // 通过参数指定 IsCompleted 为 true,只需同步调用 GetResult 方法
            string result = await GetDynamicAwaitableObject(true);
            Console.WriteLine(result);

            // 通过参数指定 IsCompleted 为 false,则会先执行 OnCompleted 方法
            result = await GetDynamicAwaitableObject(false);
            Console.WriteLine(result);
        }

        static dynamic GetDynamicAwaitableObject(bool completeSynchronously)
        {
            // ExpandoObject 类型可在运行时动态添加和删除其成员的对象
            dynamic result = new ExpandoObject(); // 类型 t
            dynamic awaiter = new ExpandoObject(); // 类型 A

            awaiter.Message = "Completed synchronously";
            awaiter.IsCompleted = completeSynchronously;
            awaiter.GetResult = (Func<string>)(() => awaiter.Message);

            awaiter.OnCompleted = (Action<Action>)(callback => ThreadPool.QueueUserWorkItem(state =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(3));
                awaiter.Message = GetInfo();
                callback?.Invoke();
            }));

            // 使用 Impromptu.ActLike 方法动态的创建代理对象,该对象将实现任何需要的接口
            IAwaiter<string> proxy = Impromptu.ActLike(awaiter);

            // t 有一个名为 GetAwaiter 的可访问的实例或扩展方法
            result.GetAwaiter = (Func<dynamic>)(() => proxy);

            return result;
        }

        static string GetInfo()
        {
            return $"Task is running on a thread id {Thread.CurrentThread.ManagedThreadId}. Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}";
        }
    }

    public interface IAwaiter<T> : INotifyCompletion
    {
        bool IsCompleted { get; }

        T GetResult();
    }
}

运行结果

txt
Completed synchronously
Task is running on a thread id 3. Is thread pool thread: True