The flow containing await in .NET 4.5 and Async CTP 4.0 can be stuck due to various reasons, e.g. since the remote client has not responded. Of course, WaitForAny, when we wait also for some timeout task is an obvious solution for recovery of the high-level flow. Still, this does not solve all possible problems.
I have the following questions:
What happens to the context of await which does not ever return? I understand that this will create memory leak. Am I right?
How can I check either in debugger or using the respective API how many dangling "awaiter"s exist in the application?
Is it possible to enumerate them globally?
If 3. is correct, is it possible to force cancellation the tasks for these *await*s (i.e. to clean up)?
Note: In question 4 I don't ask about cancellation items to be used during explicit task creation. I mean the case when the task was created indirectly:
async Task<bool> SomeTask()
{
await Something();
...
return true;
}
Motivation for this question:
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function.
An await expression in an async method doesn't block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method. The async and await keywords don't cause additional threads to be created.
The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.
1 What happens to the context of await which does not ever return?
I believe it will cause a memory leak (if you're await
ing an I/O operation). It's best to always complete your Task
s (and this means always having your async
methods return sooner or later).
Update from svick's comment: There are situations where this would not cause a memory leak.
2 How can I check either in debugger or using the respective API how many dangling "awaiter"s exist in the application?
I'm not sure if there's an easy way to do this. I believe it should be possible to write a debugger plugin that uses SoS to find existing heap objects that match the pattern of the asynchronous state machines generated by the compiler.
But that's a lot of work for little benefit.
3 Is it possible to enumerate them globally?
Not with the normal APIs.
If 3 is correct, is it possible to force cancellation the tasks for these awaits (i.e. to clean up)?
Even if you could enumerate them at runtime (e.g., via the profiling API), you can't "force" cancellation onto a task. Cancellation is cooperative.
The correct way to deal with this is with standard cancellation. The Task-based Asynchronous Pattern document specifies guidelines for cancelable async
methods.
At the lowest level: Many async
APIs in the BCL take an optional CancellationToken
.
At a middle level: It's common to have an async
method take an optional CancellationToken
and just pass it on to other async
methods.
At the highest level: It's easy to create a CancellationToken
that will fire after a given time.
About questions 2 and 3 I have no real answer.
Having tasks around that never return is hardly ever a good thing. To avoid this and to answer point 4: tasks can be cancelled.
You need to create a cancellationtoken that you pass to the task. The task is responsible on his own to watch for the status of that cancellation token and throw an exception when cancelled. (Multiple tasks can be cancelled at once using the same token too.)
This article on MSDN shows you to do so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With