2

同僚が留守中に書いたコードをデバッグしようとしています。

呼び出しは次のとおりです。

var sw = Stopwatch.StartNew();
logger.Trace("Time A: {0}ms", sw.ElapsedMilliseconds); // Roughly 0ms
pt.Task = ProcessMetricsWorker(pt.CancelTokenSource);
sw.Stop();
logger.Trace("Time B: {0}ms", sw.ElapsedMilliseconds); // Over 20000ms!

メソッドのシグネチャは次のとおりです。

async Task ProcessMetricsWorker(CancellationTokenSource cancelTokenSource)

このメソッドの実行には約 20 秒かかります。ログによると、上記の最初の行の直前と直後に配置すると、そのasync部分が無視されているかのように、タスクが同期的に実行されています。これが起こる原因は何ですか?

awaitasync メソッド内に呼び出しがあることに注意してください。それが違いを生むとは想像できませんが、それはwhileループの中にあります。

// internal to the method referenced above
result = await metricProcessor.ProcessItem(domain);

また、非常に単純な async/await セットアップを実行する小さなテスト アプリを作成して、実行しているサーバーで await が実際に動作することを確認し、メインではなく、小さなテスト ケースで正しく動作することを確認しました。デバッグしようとしているアプリ。

4

2 に答える 2

4

すべてasyncのメソッドは、通常のメソッド呼び出しとして開始されます。非同期になるのは、(呼び出し元に譲るという意味で) 最初にawaiton awaitable (まだ完了していない) を実行するときだけです。

したがって、 で何が起こっているかについては、いくつかの可能性がありProcessMetricsWorkerます。

  • 最初の の前に、実行時間の長い同期コードが含まれている場合がありますawait
  • 最初に期待できることawaitの多くは、すでに完了している可能性があります。それらがすべてすでに完了している場合、ProcessMetricsWorker実際には同期しています。

「高速パス」のブログ投稿には、 がコードに変換される方法の詳細が含まれてawaitおり、未完了の awaitable に作用する場合にのみ生成される方法が示されています。

于 2012-01-06T14:41:43.740 に答える
0

Async CTP でバグを見つけたと思います。

このメソッドを追加しました:

async Task DummyTask()
{
    await TaskEx.Run(() => Thread.Sleep(1000));
}

次に、これをProcessMetricsWorkerメソッド内に追加しました:

await DummyTask();

早速ですが、メソッドは非同期になりました。コンパイラが何らかの方法でメソッドの内部 await 呼び出しを無視し、MSIL コードですべてが同期したかどうか疑問に思っています...

于 2012-01-06T09:46:02.980 に答える