C# async/await await doesn't await - c#

I am using .Net 4.7.2 and C# 7
In a class there are serveral methods, all void. Some of them can be executed asynchronously, others have to be executed sequentially. So I defined a list for the parallels
private void ExecuteSequential()
{
SomeMethod1();
SomeMethod2();
ExecuteParallelAsync();
SomeMethod3();
SomeMethod4();
}
private async void ExecuteParallelAsync()
{
List<Action> methods = new List<Action>()
{
MyMethod1,
MyMethod2,
MyMethod3
};
await Task.Run( () => { Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() ); } );
}
Before SomeMethod3 happens to be executed ExecuteParallelAsync should be finished entirely.
Because that's not the case, apparently something is wrong with my usage of async and await.
What I am doing wrong?
Thanks in advance!

async void - all bets are off; in reality, you should never write an async void method unless you're in the tiny tiny set of extreme corner cases that require it, such as async event-handlers.
Before SomeMethod3 happens to be executed ExecuteParallelAsync should be finished entirely.
how could it possibly know? it is: async void, which means it doesn't give anything to the caller that indicates the state.
To do that, it must be:
private async Task ExecuteParallelAsync() // or ValueTask
and you must await it at the call site
await ExecuteParallelAsync();

Marc's answer is the correct solution, but I wanted to explain more about why.
A very key thing to understand about async methods is that:
They start synchronously.
When the await keyword is used, and await given an incomplete Task, the method returns - yes, even if you're only halfway through your method. The magic is in what it returns.
So lets look at what your code does:
Call ExecuteParallelAsync().
ExecuteParallelAsync() starts running synchronously.
Task.Run returns a Task object that is not complete yet.
The await keyword inspects the Task, sees that it is not complete, so it creates a new Task, signs up the rest of the method as a continuation of that Task (there is nothing left to do in this case, but it still happens) and returns.
Because the return type is void it cannot return a Task. But it still returns!
So all that means that ExecuteParallelAsync() returns before the Task.Run is completed, and ExecuteSequential() has no way to tell when the work is actually complete.
This is commonly called "fire and forget" (i.e. "go do this and I don't care when or if you finish").
As Marc's answer points out, if you want to know when it's done, you need to return a Task, which you can then await to know when it's done.
Microsoft has very well written articles about asynchronous programming that you may benefit from reading: Asynchronous programming with async and await

If you want an implementation without async/await sugar keyword:
private void ExecuteParallelAsync()
{
List<Action> methods = new List<Action>()
{
MyMethod1,
MyMethod2,
MyMethod3
};
Task.WaitAll(methods.Select((action) => Task.Run(action)).ToArray())
}

Step 1, reproduce
public void Method()
{
SomeMethod();
SomeMethod();
ExecuteParallelAsync(); //< ---fire and forget
SomeMethod();
SomeMethod();
Console.ReadLine();
}
private void SomeMethod() => Console.WriteLine($"SomeMethod");
private async void ExecuteParallelAsync()
{
Console.WriteLine($"START");
await Task.Delay(TimeSpan.FromMilliseconds(100));
Console.WriteLine($"END");
}
Output
SomeMethod
SomeMethod
START
SomeMethod
SomeMethod
END
Step 2, trying to fix
"Oh yes, I forgot to await my function"
await ExecuteParallelAsync(); //Change 1. "I forgot to await"
Output
Compilation error (line 12, col 3): The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
Compilation error (line 12, col 3): Cannot await 'void'
Step 3, fix
Addressing both errors from step 2.
// Change 2
// was:public void Main()
// which caused: "The 'await' operator can only (...)"
public async Task Main()
(...)
// Change 3
// was: private async void ExecuteParallelAsync()
// which caused "Compilation error (line 12, col 3): Cannot await 'void'"
private async Task ExecuteParallelAsync()
Run.
Output:
SomeMethod
SomeMethod
START
END
SomeMethod
SomeMethod
For reference, we could have waited for ExecuteParallelAsync without the await keyword, but await is the correct way in all scenarios except the tiny minority where it's not.

a small complete example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace test
{
class Program
{
static void Main(string[] args)
{
SomeMethod1();
ExecuteParallelAsync();
SomeMethod2();
Console.ReadKey();
}
static void SomeMethod1()
{
Console.WriteLine("SomeMethod1");
}
static void SomeMethod2()
{
Console.WriteLine("SomeMethod2");
}
static void ExecuteParallelAsync()
{
Console.WriteLine("\tstart of ExecuteParallelAsync");
var rd = new Random();
List<Action> methods = new List<Action>()
{
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod1"); },
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod2"); },
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod3"); },
};
Task.WaitAll(methods.Select((action) => Task.Run(action)).ToArray());
Console.WriteLine("\tend of ExecuteParallelAsync");
}
}
}
example of a result:
SomeMethod1
start of ExecuteParallelAsync
MyMethod2
MyMethod3
MyMethod1
end of ExecuteParallelAsync
SomeMethod2

Related

Lack of await warning in async method that has await in a lambda

Either Visual Studio is confused, or I am (probably me).
If I have
public async Task<Response> DoSomething()
{
//stuff
listOfStuff.ForEach(async s => await _repo.DoThing(s));
return new Response(listOfStuff.Count);
}
It complains that
This async method lacks 'await' ...
However if I change my method to
public async Task<Response> DoSomething()
{
//stuff
foreach (var s in listOfStuff)
{
await _repo.DoThing(s);
}
return new Response(listOfStuff.Count);
}
Then it is perfectly happy and the warning goes away.
So twofold question, is the warning correct and if it is, what is the reasoning for the difference? I'm under the impression that the two methods are intrinsically the same, if the warning is correct, then I must assume that my impression is wrong.
In the first version, the DoSomething function lacks an await operator. The only await is within the async void lambda passed to the ForEach method. In the second version the DoSomething function has an await as part of the actual body of the function and thus you get no warning. It doesn't matter if the listOfStuff may or may not be empty, the condition that the method needs an await is satisfied.
Now the functional difference may not be immediatly clear but it is critical. As stated the first version uses an async void method. That is un-awaitable and the method will therefore continue before the async operation completes as you can see with this test:
[Test]
public void DoSomething()
{
var sw = Stopwatch.StartNew();
var list = Enumerable.Range(0, 10).ToList();
list.ForEach(async x => await Task.Delay(TimeSpan.FromSeconds(1)));
Console.WriteLine($"{sw.ElapsedMilliseconds}ms");
}
Result 6ms, not the 10 seconds we'd expect. The second version of your code is a properly awaitable async Task:
[Test]
public async Task DoSomething()
{
var sw = Stopwatch.StartNew();
var list = Enumerable.Range(0, 10).ToList();
foreach(var x in list)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
Console.WriteLine($"{sw.ElapsedMilliseconds}ms");
}
And we see the result is: 10032ms right within expectations.
If we replace the lambda with a local function, things may become clearer:
public async Task<Response> DoSomething()
{
//stuff
listOfStuff.ForEach(ProcessStuffAsync);
return new Response(listOfStuff.Count);
async Task ProcessStuffAsync(Stuff s) // local function
{
await _repo.DoThing(s);
}
}
The DoSomething method returns a Task, but it is not really asynchronous because it lacks an await. So the Task returned will be in a completed state. All code inside DoSomething (excluding the code inside the local function) will run synchronously.
The local function ProcessStuffAsync is trully asynchronous, and will return one Task each time is called. These tasks are neither awaited nor stored somewhere inside the DoSomething method, so they are fire-and-forget tasks. Nobody knows what's gonna happen to them.
Update: The code above doesn't compile because List.ForEach cannot accept the ProcessStuffAsync local function as argument. The compiler complains that it has wrong return type. To make the code compile, the local function must return void. But async void functions are a can of worms by themselves.

C# Async, why we need to "hold" the console to get the async result?

For the past several days, I've been trying to figure out why my async method is not working and its a very simple piece of code.
public class EntryPoint
{
static void Main()
{
RunTheTaskAsync();
//Console.ReadLine(); // if I add this to "hold" the finish of the project, I will see the result, without it I dont
}
public async static void RunTheTaskAsync()
{
Task<string> task = Concatenator('1', 200000);
Console.WriteLine("Heeeelllooooooo");
Console.WriteLine("I am running while Concatenator is concatenating in the background.");
Console.WriteLine("You will receive the results shortly");
string result = await task;
Console.WriteLine("Result is: " + result.Length);
}
public static Task<string> Concatenator(char characterToConcatenate, int count)
{
Console.WriteLine("Concatenating!");
return Task<string>.Factory.StartNew(() =>
{
string concatenatedString = "";
for (int i = 0; i < count; i++)
{
concatenatedString += characterToConcatenate;
}
return concatenatedString;
});
}
}
If I run it as it is in the example above, I never get to see the result, I only see the Console.WriteLine's and Press any key to continue.. after that no result.
If I uncomment the Console.ReadLine(); everything works as I am expecting it to work and I simply cant understand why!?! The same is true if I add some Thread.Sleep(xxx) or another piece of code that will take longer to execute than the "Concatenator" method.
Isn't this one of the issues that await should solve on its own, its kind of implied from its very name.
The way I understand it is:
The Task method starts executing on the background
We proceed with the 3 ConsoleWritelines in the async method
Since there is nothing else to do and the task is not completed yet, we get to the await line and we should await for the task
to be completed and then proceed with the rest of the code.
It works like this ONLY if have another piece of code inbetween that will take longer than the Task method to execute, or if I use the Console.ReadLine() and I just cant find an explanation about this!
I also have a secondary question regarding the syntax of my implementation. Is this the proper way to create a Task method? By using
public Task<T> SomeMethodName(some, args)
{
return Task<T>Factory.StartNew(() =>
{
somecode that returns T;
});
}
async voids (like your RunTheTaskAsync method) are "fire and forget". You can't track their progress and almost never want to use them.
Instead, make an async Task and await it:
static async Task Main()
{
await RunTheTaskAsync();
}
public static async Task RunTheTaskAsync()
{
...
}
For more details, see:
Async/Await - Best Practices in Asynchronous Programming
Note: Visual Studio prior to 2017 Update 3 does not support an async Main method. In that case, you have to manually await the Task:
static void Main()
{
RunTheTaskAsync().GetAwaiter().Wait();
}
About your second question (for the future: SO's policy is "one question per question"): Yes, Task.Factory.StartNew is correct if you need your task to run in a separate thread. Newer versions of .NET as offer Task.Run as a shortcut, see the following question for details:
What is the difference between Task.Run() and Task.Factory.StartNew()

What's the difference between awaiting async Task function and calling await inside a void function?

To understand the question please take a look on the await calls and the definition of the function InitSyncContext() of the following example.
Based on that i would like to know how the program will behave on each scenario because i don't fully understand what´s the difference between calling await InitSyncContext(store) and having a await call inside without returning a Task.
For reference i did a research before and i found a similar example here however i think it's different in my case.
*The following code is a simplified example from a real world code just for demonstration purposes.
void Main()
{
Initializer();
}
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
InitFileSync(store);
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
//------------- Second Method -------------
void Main()
{
Initializer();
}
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
InitFileSync(store);
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
What's the difference between awaiting async Task function and calling await inside a void function?
This is perhaps a very big question is best served by reading the fine article Async/Await - Best Practices in Asynchronous Programming by Mr Stephen Cleary.
Some summary points:
Avoid async void - Prefer async Task methods over async void methods
See also
Cleary, S, "Async/Await - Best Practices in Asynchronous Programming", March 2013, Microsoft, https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396, retrieved 14/7/2016
What's the difference between awaiting async Task function and calling await inside a void function?
The whole world! Everything...and then some. Let's take a step back and start with some of the basics.
You should go "async all the way", i.e.; if you're returning an awaitable (Task or Task<T>) these should correctly use the async and await keywords.
There are several things that need to be clarified here. You should not have async void methods, instead you should have async Task - the exception being event handlers (where the delegates are predefined as non-task returning) and the like. Let's examine and pick apart method one (I'm going to ignore the Main entry points):
One
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
...
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
You have an Initializer method that is immediately a code smell as it is async void. This should be async Task and it should have the "Async" suffix. Additionally, you have an InitSyncContext that takes on a store variable and invokes some client initialization work. The code smell here is that you are using async and await. This is not need on simple (single task) workloads like this. Instead you should simply use the return keyword. Example at the very bottom. Let's look at method two:
Two
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
...
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
Things have officially gone from bad to worse! With the misconceptions of the asynchronous nomenclatures, we have assumed that since one method appeared to work "ok" without taking into account the best practices that another method could follow suit. You made the InitSyncContext method async void. The reason methods should not be async void is that they are fire-and-forget. The internal async state machine doesn't have a Task to latch onto and therefore the state is lost. When you remove the caller's await you are saying start this asynchronous operation but you do not care about it's results.
Here is the correct way to implement the desired functionality:
Correct
private async Task InitializerAsync()
{
var store = InitLocalStore();
await InitSyncContextAsync(store);
...
}
// Simply return the task that represents the async operation and let the caller await it
private Task InitSyncContextAsync(MobileServiceSQLiteStore store)
{
return Client.SyncContext.InitializeAsync(store);
}
A note about the Main method from your snippets, if this is part of a console application - the top-level entry point into your async stack would invoke either .Result or .Wait().
Further reading
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396
In first example compiler generate something like this:
TheadPool.RunTask(()=>InitSyncContext(store)).ContinueWith(()=>InitFileSync(store))
At second — nothing interesting. Because nobody wait the end of the task. All calls will be in main thread exept await Client.SyncContext.InitializeAsync(store);

Wait for a void async method

How can I wait for a void async method to finish its job?
for example, I have a function like below:
async void LoadBlahBlah()
{
await blah();
...
}
now I want to make sure that everything has been loaded before continuing somewhere else.
Best practice is to mark function async void only if it is fire and forget method, if you want to await on, you should mark it as async Task.
In case if you still want to await, then wrap it like so await Task.Run(() => blah())
If you can change the signature of your function to async Task then you can use the code presented here
The best solution is to use async Task. You should avoid async void for several reasons, one of which is composability.
If the method cannot be made to return Task (e.g., it's an event handler), then you can use SemaphoreSlim to have the method signal when it is about to exit. Consider doing this in a finally block.
You don't really need to do anything manually, await keyword pauses the function execution until blah() returns.
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T is type of object blah() returns
You can't really await a void function so LoadBlahBlah() cannot be void
I know this is an old question, but this is still a problem I keep walking into, and yet there is still no clear solution to do this correctly when using async/await in an async void signature method.
However, I noticed that .Wait() is working properly inside the void method.
and since async void and void have the same signature, you might need to do the following.
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
Confusingly enough async/await does not block on the next code.
async void LoadBlahBlah()
{
await blah(); //this does not block
}
When you decompile your code, my guess is that async void creates an internal Task (just like async Task), but since the signature does not support to return that internal Tasks
this means that internally the async void method will still be able to "await" internally async methods. but externally unable to know when the internal Task is complete.
So my conclusion is that async void is working as intended, and if you need feedback from the internal Task, then you need to use the async Task signature instead.
hopefully my rambling makes sense to anybody also looking for answers.
Edit:
I made some example code and decompiled it to see what is actually going on.
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
Turns into (edit: I know that the body code is not here but in the statemachines, but the statemachines was basically identical, so I didn't bother adding them)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
neither AsyncVoidMethodBuilder or AsyncTaskMethodBuilder actually have any code in the Start method that would hint of them to block, and would always run asynchronously after they are started.
meaning without the returning Task, there would be no way to check if it is complete.
as expected, it only starts the Task running async, and then it continues in the code.
and the async Task, first it starts the Task, and then it returns it.
so I guess my answer would be to never use async void, if you need to know when the task is done, that is what async Task is for.
do a AutoResetEvent, call the function then wait on AutoResetEvent and then set it inside async void when you know it is done.
You can also wait on a Task that returns from your void async
You can simply change the return type to Task and call await Task.CompletedTask at the end of the function, e.g:
async Task MyFunction() {
await AnotherFunction();
await Task.CompletedTask;
}
I find this simpler than wrapping the whole function body in a call to Task.Run(() => { ... });.
I've read all the solutions of the thread and it's really complicated... The easiest solution is to return something like a bool:
async bool LoadBlahBlah()
{
await blah();
return true;
}
It's not mandatory to store or chekc the return value. You can juste do:
await LoadBlahBlah();
... and you can return false if something goes wrong.

Calling an async method from a non-async method

Every variation on the following code that I try doesn't work - whether DoSomething() : void and is called as written, or DoSomething() : Task and is called with TaskEx.RunEx(), some attempt involving .GetAwaiter().GetResult(). Errors seen include: "Start may not be called on a task with null action", "RunSynchronously may not be called on a task unbound to a delegate", and "The task has not yet completed".
class Program
{
static void Main(string[] args) // Starting from a non-async method
{
DoSomething();
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
static async void DoSomething()
{
Console.WriteLine("Starting DoSomething ...");
var x = await PrepareAwaitable(1);
Console.WriteLine("::" + x);
var y = await PrepareAwaitable(2);
Console.WriteLine("::" + y);
}
static Task<string> PrepareAwaitable(int id)
{
return new Task<string>(() =>
{
return "Howdy " + id.ToString();
});
}
}
Output:
Starting DoSomething ...
Press any key to quit.
PrepareAwaitable's Task's Action will be more complicated later. When this action completes, however long that takes, I would expect the Task (or other Framework mechanisms) to resume by assigning "Howdy ..." to x, and then later to y. What I REALLY want to do is intercept the awaited objects, process them, and at some later time that I control, resume to the continuation with a result (x and y). But I haven't been getting very far on that big step, so I'm trying to start smaller.
First, read the Task-Based Asynchronous Pattern document. It's under My Documents\Microsoft Visual Studio Async CTP\Documentation. This document describes how to design APIs naturally consumable by await.
Secondly, realize that there are several aspects of the Task class and related APIs that no longer really apply in the new asynchronous world. Task was originally written as the core of TPL. It turned out to be a good fit for asynchronous programming, so Microsoft used it instead of creating a new "Promise" class. But a number of methods are holdovers, used by TPL but not needed for async programming.
To answer the titular question, mixing synchronous and asynchronous code is not quite straightforward with the current async CTP. I've written a library that includes a Task.WaitAndUnwrapException extension method, which makes it easy to call async code from sync code. You may also be interested in my AsyncContext class, which makes the "press any key" prompt unnecessary.
The tasks you returned haven't started yet (i.e., they're "cold" tasks); try replacing the PrepareAwaitable code with the following:
static Task<string> PrepareAwaitable(int x)
{
return Task.Factory.StartNew<string>(() =>
{
return "Howdy " + x.ToString();
});
}
It's really not clear what you're trying to achieve, because there's nothing asynchronous going on. For example, this will compile and run, but I don't know whether it's what you want:
using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
DoSomething();
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
static async void DoSomething()
{
Console.WriteLine("Starting DoSomething ...");
var x = await PrepareAwaitable(1);
Console.WriteLine("::" + x);
var y = await PrepareAwaitable(2);
Console.WriteLine("::" + y);
}
static async Task<string> PrepareAwaitable(int x)
{
return "Howdy " + x;
}
}
Note that this gives a warning for PrepareAwaitable because there's nothing asynchronous in it; no "await" expressions. The whole program executes synchronously. Another alternative implementation of PrepareAwaitable:
static Task<string> PrepareAwaitable(int x)
{
return TaskEx.Run(() => "Howdy " + x);
}
Is that more like what you were after?
add GetAwaiter().GetResult() after your async task should work. But for eliminating errore like "...not be called on a task with null action", you simply have your Task<IHttpActionResult> to return Ok(true) rather than Ok().
It fixed the GetResult() issue for me !

Categories