Wrapping async methods
async-await, asynchronous, c#
Solution
By default the `await` keyword is built to try to keep as much of the original code as possible running on the original thread (or, at least, in the same "context" as the code that runs before the `await`, e.g. if you were running in the thread pool previously, any thread pool thread will do).
What's happening is that all of your original code, when it can run, wants to run on the UI thread.
But you're blocking the UI thread in that `Wait` so it's never available to run the remainder of the code inside your `async` method and so complete the outer `Task`. I.e. there's just this little bit of code left to run in your method, after the `Task.Delay` task has completed:
public class Test
{
public async Task Delay()
{
await Task.Delay(1000);
//<-- This "Code" needs to run before my Task is completed
}
}
You can use `ConfigureAwait(continueOnCapturedContext)` to request that this not happen:
continueOnCapturedContext
true to attempt to marshal the continuation back to the original context captured; otherwise, false.
See also this old blog post by Eric Lippert, from when `async` was new:
The “async” modifier on the method does not mean “this method is automatically scheduled to run on a worker thread asynchronously”. It means the opposite of that; it means “this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot.” The whole point of async methods it that you stay on the current thread as much as possible.
Problem
I have a strange behaviour concerning wrapping asynchronous methods in C#. It is difficult to cut out the portion of my code that has this strange behaviour, so instead I made a test project to investigate the behaviour, and this is what I have found out. I have a test class which has an async method that is simply a wrapper of another async method: (In my original code it is a wrapper class which contains 2 objects, which it has wrapper methods for) ``` public class Test { public async Task Delay() { await Task.Delay(1000); } } ``` In my test program I am running the following code from an async event handler: (In my case the Loaded event, since I am using a WPF Window) ``` var test = new Test(); await Task.Delay(1000); await test.Delay(); Task.Delay(1000).Wait(); test.Delay().Wait(); ``` All is well until the last line, which never returns. Then I tried changing the test class to the following and the last line works: ``` public class Test { public Task Delay() { return Task.Delay(1000); } } ``` My question is why the first scenario does not work?