1

非同期を調査していますが、説明できない次の結果に出くわしました。

次のコード (コピーして Linqpad などに貼り付けることができます) は、スレッド プールから 3 つのスレッドを使用するという驚くべき結果をもたらします。

void Main()
{
    Wait();
}

public async void Wait()
{
    Print ("Wait() called. Calling GetAnswer()");
    var t = await GetAnswerAsync3();
    Print("Result of Wait(): " + t);
}

public Task<bool> GetAnswerAsync3()
{
    return Task.Run(() => {
            // Thread.Sleep(1000);
        Print("GetAnswerAsync3() called");
        return true;
    });
}

public void Print(string message)
{
    Console.WriteLine ("Thread: " + Thread.CurrentThread.ManagedThreadId + " - " + message);
}

結果は次のとおりです。

Thread: 35 - Wait() called. Calling GetAnswer()
Thread: 51 - GetAnswerAsync3() called
Thread: 43 - Result of Wait(): True

3 つのスレッドが関係していることを示しています。

今。Thread.Sleep(1000)Task が返す前にa を追加するとGetAnswerAsync3、実行中のスレッドは 2 つだけになります。おそらくこれは、スレッドプールがスレッドを再利用するためでしょうか?

ここで 3 つの異なるスレッドが動作しているのはなぜですか?

4

1 に答える 1

3

メソッドはいくつかのasync作業に分割され、この場合はすべてスレッド プールにスケジュールされます。メソッドが「壊れる」可能性がawaitある場所を指定します。async

最初のスレッドは、スレッド プールの一部ではないメイン スレッドです。

2 番目のスレッドは、 に渡されたデリゲートを実行するために使用されるスレッドですTask.Run。これは、スレッド プールの任意のスレッドにすることができます。

3 番目のスレッドは、 の実行を取得するために使用されるスレッドWaitですawait。これは、スレッド プールの任意のスレッドでもかまいません。

概念的には、それが起こります。実際には、もう少し複雑です。

最初の方が説明しやすいと思いますThread.Sleep。この場合、が完了する前に完全にWait中断されています。が完了すると、その継続が実行され、メソッドの継続が設定されます (私のブログで説明されています)。したがって、実行中の同じスレッドは、実際には譲らずに実行を続けます。awaitTask.RunTask.RunasyncExecuteSynchronouslyThread.SleepWait

元のコードに競合状態があります。Task.Run非常に短いため、すぐに完了します。あなたが見ているのは、をWaitチェックしてTask、まだ完了していないことを確認し、Waitメソッドを一時停止することです。その間、 がTask.Run完了し、残りのWaitスレッド プールをスケジュールします。

awaitがコンテキストでどのように機能するかについて詳しく知りたい場合は、 asyncintroをお勧めします。通常、このような詳細について心配する必要はありません。

于 2013-07-01T17:38:26.780 に答える