Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't a method containing an async lambda need to be Async itself?

For example, whenever I await something the compiler notifies me the containing method must be Async. Why is the async lamba not seen this way? If the ForEach is hiding it then is there some danger regarding not returning a Task object and the ForEach being implicitly async void?

public void SaveSome()
{
    Array.ForEach(Enumerable.Range(0,3).ToArray(), async x =>  await SaveRep());
}
like image 538
Jaycee Avatar asked Sep 12 '13 11:09

Jaycee


People also ask

What happens if you do not await an async method?

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.

What is an async lambda?

For asynchronous invocation, Lambda places the event in a queue and returns a success response without additional information. A separate process reads events from the queue and sends them to your function. To invoke a function asynchronously, set the invocation type parameter to Event .

Why you shouldn't use async void?

Async void methods can wreak havoc if the caller isn't expecting them to be async. When the return type is Task, the caller knows it's dealing with a future operation; when the return type is void, the caller might assume the method is complete by the time it returns.

Should all methods be async?

If a method has no async operations inside it there's no benefit in making it async . You should only have async methods where you have an async operation (I/O, DB, etc.). If your application has a lot of these I/O methods and they spread throughout your code base, that's not a bad thing.

How do I run an async lambda function in startnew?

The task created by StartNew will invoke the Func<Task<int>>, which will run synchronously until the first await that yields, at which point the Func<Task<int>> will return, handing back the result Task<int> that represents the async lambda’s execution.

When to use asynchronous functions in AWS Lambda?

When this is the case, asynchronous functions are the way to go. One example of when you would want to run an asynchronous function is when you are starting a video encoding process. AWS Lambda will send a response that the video encoding function has been invoked and started successfully.

Can the ‘await’ operator be used within an async lambda expression?

error CS4034: The ‘await’ operator can only be used within an async lambda expression. Consider marking this lambda expression with the ‘async’ modifier.

Why is my async method not running synchronously?

If the method doesn’t have any awaits in it, or if all of the awaits in the method are on awaitables that are already completed by the time they’re awaited, then the method will run entirely synchronously. However, when the method encounters the first await that yields, the async method returns.


2 Answers

You can only await an async method in an async method, but you can still call them in a non-async method, like you're doing above - in this case, it's more a "fire and forget"

like image 198
Rowland Shaw Avatar answered Oct 08 '22 22:10

Rowland Shaw


An async lambda is just a simple way of creating a delegate which is asynchronous. There's nothing to say that the method which contains it has to be doing anything asynchronous itself - and any await expressions within the lambda expression won't make the containing method wait (unless it's awaiting a task which happens to rely on the delegate, of course).

Basically the lambda expression is expressing some asynchronous code - it's not executing the asynchronous code itself... so the containing method isn't necessarily executing asynchronously.

Yes, the example you've given is a misuse of async lambdas - but making the method async wouldn't improve matters at all, and it would simply be misleading.

EDIT: As an alternative way of thinking about it, consider this refactoring of your original code:

public void SaveSome()
{
    Action<int> action = SaveRepAsync;
    Array.ForEach(Enumerable.Range(0,3).ToArray(), action);
}

private static async void SaveRepAsync(int x)
{
    await SaveRep();
}

The SaveSome method has nothing asynchronous about it - only the SaveRepAsync method does... so that's what requires the async modifier. This really is just a tiny refactoring of your code (the sort of refactoring the compiler would do, effectively). If you wanted every method containing an async lambda to have the async modifier, that's like saying that in the above code, SaveSome should have the modifier too... which would make no sense, IMO.

like image 37
Jon Skeet Avatar answered Oct 08 '22 20:10

Jon Skeet