私は新しい C# の await 機能を試していました。次のようにカスタム awaiter 実装を作成しました。
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 はスレッド プールを内部的に使用することを知っています。これは、スレッド アプローチと同じように機能するはずです (スレッド プールにはスレッド数の制限があることはわかっていますが、この場合は他に何も実行していないため無視できます)。
あなたのアイデアは何ですか?ありがとう!