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部分被忽略了一样。什么会导致这种情况发生?

请注意,await异步方法内部有一个调用。它在一个while循环内,但我无法想象这会有所作为。

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

此外,我创建了一个小型测试应用程序,它运行一个非常简单的 async/await 设置,以确保 await 在我正在运行它的服务器上实际工作,并且它在我的小测试用例中正常工作,只是在主用例中没有我正在尝试调试的应用程序。

4

2 回答 2

4

每个async方法都作为常规方法调用启动。它仅在第一次await对可等待对象(尚未完成)执行操作时才变为异步(在屈服于其调用者的意义上)。

所以,有几种可能发生的事情ProcessMetricsWorker

  • 它可能在第一个await.
  • 它的许多第一个 awaitablesawait可能已经完成。如果它们都已经完成,那么ProcessMetricsWorker实际上是同步的。

“快速路径”博客文章包含有关如何将 anawait转换为代码的更多详细信息,并展示了它如何仅在它作用于未完成的 awaitable 时才产生。

于 2012-01-06T14:41:43.740 回答
0

好吧,我想我在 Async CTP 中发现了一个错误。

我添加了这个方法:

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

然后在ProcessMetricsWorker方法中添加这个:

await DummyTask();

嘿 presto,该方法现在是异步的!我想知道编译器是否以某种方式忽略了方法中的内部等待调用,而这一切都在 MSIL 代码中同步出现......

于 2012-01-06T09:46:02.980 回答