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.
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 an await
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, then ProcessMetricsWorker
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.