4

await Thread.SleepAsync()追加のスレッドを作成せずに実行するのを待つことができるカスタムを実装しようとしています。

これが私が持っているものです:

    class AwaitableThread : INotifyCompletion
    {
        public AwaitableThread(long milliseconds)
        {
            var timer = new Timer(obj => { IsCompleted = true; }, null, milliseconds, Timeout.Infinite);
        }

        private bool isCompleted = false;

        public bool IsCompleted
        {
            get { return isCompleted; }
            set { isCompleted = value; }
        }

        public void GetResult()
        {}

        public AwaitableThread GetAwaiter() { return this; }

        public void OnCompleted(Action continuation)
        {
            if (continuation != null)
            {
                continuation();
            }
        }
    }

そして、これが睡眠がどのように機能するかです:

    static async Task Sleep(int milliseconds)
    {
        await new AwaitableThread(milliseconds);
    }

OnCompleted問題は、がまだfalseであっても、この関数がすぐに返されることIsCompletedです。

私は何が間違っているのですか?

4

1 に答える 1

10

本番環境で使用するために待機可能なパターンを完全に実装するのは難しいビジネスです。特に、実行コンテキストをキャプチャする必要があります。これに関するStephenToubのブログ投稿には、さらに多くの詳細があります。多くの場合、Task<T>またはにピギーバックする方が簡単で、場合によってはTaskを使用しTaskCompletionSourceます。たとえば、あなたの場合、次のTask.Delayように同等のものを書くことができます。

public Task MyDelay(int milliseconds)
{
    // There's only a generic TaskCompletionSource, but we don't really
    // care about the result. Just use int as a reasonably cheap version.
    var tcs = new TaskCompletionSource<int>();

    Timer timer = new Timer(_ => tcs.SetResult(0), null, milliseconds,
                            Timeout.Infinite);
    // Capture the timer variable so that the timer can't be garbage collected
    // unless the task is (in which case it doesn't matter).
    tcs.Task.ContinueWith(task => timer = null);

    return tcs.Task;
}

awaitこれで、の結果を待つことができるのと同じように、そのタスクを実行できますTask.Delay

于 2012-11-17T13:15:00.670 に答える