2

現在、C# の詳細 (第 3 版) を読んでいますが、表示された警告の 1 つは、GUI スレッドを task.wait で使用するとデッドロックが発生する可能性があるため危険であるというものです。ただし、ThreadPool または Console の問題ではありません。私の質問は、なぜ task.wait を実行しているスレッドがデッドロックしないので、次のコード (本から取得) の場合、コンソール アプリ (バックラウンド) スレッドでさえ、デッドロックするためキャッチに到達しないのです。

public static void Main(string[] args = null)
{
        var source = new CancellationTokenSource();
        var task = TestInt(source.Token);
        source.CancelAfter(4000);
        Console.WriteLine("Status {0}",task.Status);
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            Console.WriteLine("Caught {0}",e.InnerExceptions[0]);
        }
        Console.WriteLine("Final Status: {0}",task.Status);
        Console.ReadKey();
    }

    public static async Task TestInt(CancellationToken token, double start = 1)
    {

        await Task.Delay(TimeSpan.FromSeconds(30), token);
    }

ありがとうございます

4

1 に答える 1

6

これについては、ブログ投稿で詳しく説明しています。

何が起こるかというと、(デフォルトで)await現在の「コンテキスト」をキャプチャし、そのコンテキストを使用してasyncメソッドの実行を再開します。この「コンテキスト」はである場合をSynchronizationContext.Current除きnull、 である場合は ですTaskScheduler.Current

あなたの例では、SynchronizationContext.CurrentisnullTaskScheduler.Currentis TaskScheduler.Default、つまり、スレッド プールのタスク スケジューラです。したがって、asyncメソッドはスレッド プール スレッドで再開され、デッドロックは発生しません。スレッド プール スレッドはasyncメソッドを終了し、を完了してTask、メイン スレッドが待機を終了できるようにします。

(デッドロックの場合、SynchronizationContextUI スレッドを表す があるため、asyncメソッドは UI スレッドで再開しようとしますが、UI スレッドは の呼び出しによってブロックされますWait)。

于 2013-10-31T13:23:01.570 に答える