0

我正在试验新的 C# 等待功能。我做了一个自定义等待器实现如下:

using System;
using System.Runtime.CompilerServices;
using System.Threading;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            T1();
            Console.WriteLine("After t1");
        }

        private static async void T1()
        {
            CustomAwaitable a = new Sleeper().Sleep();
            object r = await a;
            Console.WriteLine("sleeper awakes " + r);
        }
    }

    internal class CustomAwaitable
    {
        private readonly Sleeper m_sleeper;

        public CustomAwaitable(Sleeper s)
        {
            m_sleeper = s;
        }

        public MyAwaiter GetAwaiter()
        {
            return new MyAwaiter(m_sleeper);
        }
    }

    internal class Sleeper
    {
        public ManualResetEvent Handle = new ManualResetEvent(false);

        public bool Awake { get; set; }

        public int Result
        {
            get { return Environment.TickCount; }
        }

        public CustomAwaitable Sleep()
        {
            new Thread(() =>
            {
                Thread.Sleep(5000);
                Awake = true;
                Handle.Set();
            }).Start();
            Console.WriteLine("begin sleeping " + Result);
            return new CustomAwaitable(this);
        }
    }

    internal class MyAwaiter : INotifyCompletion
    {
        private readonly Sleeper m_sleeper;

        public MyAwaiter(Sleeper sleeper)
        {
            m_sleeper = sleeper;
        }

        public bool IsCompleted
        {
            get { return m_sleeper.Awake; }
        }

        public void OnCompleted(Action continuation)
        {
            // This works!!
            //new Thread(() => 
            //{
            //  m_sleeper.Handle.WaitOne();
            //  continuation();
            //}).Start();

            // This doesn't work!!
            Action k = () =>
            {
                m_sleeper.Handle.WaitOne();
                continuation();
            };

            k.BeginInvoke(null, null);
        }

        public object GetResult()
        {
            return m_sleeper.Result;
        }
    }
}

问题是,在 OnCompleted 方法中,当我使用 BeginInvoke 安排继续代码执行时,永远不会调用 GetResult 方法。但是当我手动创建一个线程来做同样的事情时,一切都按预期工作。我知道 BeginInvoke 在内部使用线程池,它的工作方式应该与线程方法相同(我知道线程池有线程数限制,但在这种情况下可以忽略不计,因为我没有运行其他任何东西)。

你有什么想法?谢谢!

4

0 回答 0