什么会导致标有 async 的方法同步执行,即使它包含 await 调用?
我正在尝试调试我的同事在他离开时编写的一些代码。
这是调用:
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 秒才能运行,根据我在上面引用的第一行之前和之后放置的日志记录,该任务正在同步执行,就像异步执行一样部分被忽略。什么会导致这种情况发生?
请注意,异步方法内有一个 await
调用。它在 while 循环内,尽管我无法想象这会产生影响。
// internal to the method referenced above
result = await metricProcessor.ProcessItem(domain);
另外,我创建了一个小型测试应用程序,它运行一个非常简单的异步/等待设置,以确保等待实际上在我运行它的服务器上工作,并且它在我的小测试用例中确实工作正常,只是不在主测试用例中我正在尝试调试应用程序。
I'm trying to debug some code my coworker wrote while he is away.
Here's the call:
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!
Here's the method signature:
async Task ProcessMetricsWorker(CancellationTokenSource cancelTokenSource)
The method takes around 20 seconds to run and according to logging I place immediately before and after the first line quoted above, the task is executing synchronously, as though the async
part is being ignored. What would cause this to happen?
Note that there is an await
call inside the async method. It's inside a while loop, though I can't imagine that would make a difference.
// internal to the method referenced above
result = await metricProcessor.ProcessItem(domain);
Also, I created a small test app that runs a very simple async/await setup to make sure that await actually works on the server I'm running it on, and it does work correctly in my small test case, just not in the main app I'm trying to debug.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
每个
async
方法都是作为常规方法调用启动的。仅当第一次对可等待对象(尚未完成)执行await
时,它才会变为异步(就屈服于其调用者而言)。因此,
ProcessMetricsWorker
中发生的情况有两种可能性:await
之前包含一些长时间运行的同步代码。“快速路径”博客文章包含有关如何将
await
转换为代码的更多详细信息,并展示了它如何仅在作用于未完成的可等待项时才产生结果。Every
async
method is started as a regular method call. It only becomes asynchronous (in the sense of yielding to its caller) the first time it does anawait
on an awaitable (that is not already completed).So, there's a couple possibilities of what's going on in
ProcessMetricsWorker
:await
.await
s may already be completed. If they are all already completed, thenProcessMetricsWorker
is actually synchronous.The "fast path" blog post contains more details of how an
await
is converted to code, and shows how it only yields if it acts on a non-completed awaitable.嗯,我想我在异步 CTP 中发现了一个错误。
我添加了这个方法:
然后在 ProcessMetricsWorker 方法中添加了这个方法:
嘿,很快,该方法现在是异步的!我想知道编译器是否以某种方式忽略了方法中的内部等待调用,并且所有这些都在 MSIL 代码中同步出现......
Well, I think I found a bug in the Async CTP.
I added this method:
Then added this right inside the
ProcessMetricsWorker
method:And hey presto, the method is now asynchronous! I'm wondering if the compiler somehow ignored the inner await call in the method and it all came out synchronous in the MSIL code...