3

次のコードを検討してください

    public static async Task<int> Answer()
    {
        await Task.Delay(1000);
        return 42;
    }

    static void Main(string[] args)
    {
        for (int j = 0; j < 20; j++)
        {
            Console.WriteLine(j +" " + Thread.CurrentThread.IsThreadPoolThread);
            if (j == 1)
            {
                new Task( async ()=>
                    {
                        int answer = await Answer();
                        Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
                    }).Start();
            }

            Thread.Sleep(200);
        }

        return;

CurrentThread.IsThreadPoolThreadwhen printingの答えは何だと思いますか?

Task.Delay(..)await を削除すると、答えはFalse. Delayただし、ドキュメントのスレッドプールに実際に何かを配置しているようには見えません。

これは、より一般的な質問につながります。以外に、実際にスレッド プール スレッドを開始するTaskRun(..)何ですか?

編集
置き換えnew Task(...)Ask()

    public static async void Ask()
    {
        int answer = await Answer();
        Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
    }

同じ結果が得られます

4

1 に答える 1

3

async/awaitイントロ投稿で説明したように、デフォルトでawaitは、現在の「コンテキスト」をキャプチャし、それを使用して継続を実行します ( の後のコードawait)。この「コンテキスト」はである場合をSynchronizationContext.Current除きnull、 である場合は ですTaskScheduler.Current

私のブログでは、コンソール アプリでの使用asyncについても説明しています。コンソール アプリは を提供しないSynchronizationContextため、「コンテキスト」は にフォールバックしTaskScheduler.Currentます。現在実行中Taskの はスレッド プールで実行されているため、スレッド プールのタスク スケジューラである とTaskScheduler.Current同じです。TaskScheduler.Default

これが、コードがスレッド プール スレッドで再開される理由です。それは正しい振る舞いです。

于 2012-11-01T20:23:58.880 に答える