This question already has answers here:
Any difference between "await Task.Run(); return;" and "return Task.Run()"? [duplicate]
(4 answers)
Closed 6 years ago.
Method 1:
private static async Task FirstDelayAsync()
{
await Task.Delay(1000);
}
Method 2:
private static Task SecondDelayAsync()
{
return Task.Delay(1000);
}
Please help me to find the difference:
await FirstDelayAsync();
await SecondDelayAsync();
Thanks.
The two are very similar. When it encounters an async method, the C# compiler will generate a state machine, such that the returned Task represents the completion of your method. Since the only thing that your method does is await another asynchronous operation, then this will be functionally almost equivalent to returning the Task from the inner asynchronous operation directly.
There is, however, a subtle difference concerning how exceptions from the synchronous part will be thrown. Any logic performed within async methods, including the synchronous part at the beginning of the method (before the first await statement), will be compiled as part of the asynchronous operation. This means that precondition exceptions will no longer be delivered synchronously, but asynchronously through the returned Task:
private static async Task FirstDelayAsync()
{
if (StateNotValid)
throw new NotSupportedException();
await Task.Delay(1000);
}
private static Task SecondDelayAsync()
{
if (StateNotValid)
throw new NotSupportedException();
return Task.Delay(1000);
}
Testing out the above code:
var t1 = FirstDelayAsync();
await t1; // exception thrown here
var t2 = SecondDelayAsync(); // exception thrown here
await t2;
This won't make a difference if you await your asynchronous operation on the same line that you call it. However, it would make a difference if you delay the awaiting; for example, if you launch several asynchronous operations concurrently and then await them together using Task.WhenAll:
var tasks = Enumerable
.Range(0, 10)
.Select(i => ProcessAsync(i))
.ToArray();
await Task.WhenAll(tasks);
In the above snippet, synchronous exceptions thrown from the ProcessAsync calls would prevent the subsequent asynchronous operations from even being launched, since the exception immediately stops the enumeration. This is usually preferable for failed preconditions that should stop the entire process.
Update: Another important different is that using await without ConfigureAwait(false) will make your code more liable to deadlock. See this answer.
Functionally, there is no difference between the two methods. They work the same.
async and await allow you to create complex asynchronous methods by allowing you to write code that looks like synchronous code but is actually asynchronous.
For simple cases like the one you have, the second approach is preferred since the first approach creates a state machine to handle the asynchronous logic. Such state machine is definitely needed in case of complex asynchronous methods, but is not needed for this simple case.
Related
This question already has answers here:
When does 'await' immediately leave a method and when does it not?
(6 answers)
Closed 9 months ago.
After reading a lot about async/await I still have a fundamental question (that I kind of assume the answer but I just want confirmation).
Let's discuss over some code:
async Task methodA() {
//code A (without awaits or Task.Run)
Task.Run(()=> //code A' (without awaits or Task.Run))
}
async Task methodB() {
//code B (without awaits or Task.Run)
await methodA();
}
void Main() {
//code C (without awaits or Task.Run)
methodB(); (no await)
//code D (without awaits or Task.Run, no pun intended)
}
What I think will happen:
Run code C
Run code B
Run code A
Run code A' and code D (different threads, in parallel)
The doubt comes from what's in the documentation:
The await operator suspends evaluation of the enclosing async method
until the asynchronous operation represented by its operand completes. [...]
The await operator doesn't block the thread that evaluates the async method.
The key being here what represents an asynchronous operation. Cause considering this other piece of documentation:
The await operator tells the compiler that the async method can't
continue past that point until the awaited asynchronous process is
complete. In the meantime, control returns to the caller of the async
method.
One might think that, since methodA() is async, once methodB reaches the await methodA(), then it might return control to the caller and allow to run code D in parallel to code A and code A'.
The essence is if method A constitutes an asynchronous operation as described in the documentation, or only until it reaches truly async code (code that runs on another thread) then it actually allows control to return to the caller (which in this case is code A').
My understanding is that asynchronous operation is an operation that will run on another thread, is this correct? So things like Task.Run, Task.Delay, Task.Sleep..? And that even though code A is within an async method, it is not an async operation and control does not go immediately back when awaiting methodA. Is this correct?
Just for completion, check this question where in the answer's comments they argue precisely about this, without a very clear answer.
[...], control returns to the caller of the async method.
This sentence had confused the hell out of me when I was learning asynchronous programming. What it means is that the Task is created and returned. You can think the asynchronous methods as generators for Task objects. The async method has to do some work in order to create the Task. This work completes when the first await of an incomplete awaitable inside the method is reached. At that point the Task is created, it is handed to the caller of the method, and the caller can do whatever it wants with it.
Usually the caller awaits the task, but it can also do other things before awaiting it, or it might never await it and completely ignore it, although this is not recommended. Generally you want to keep track of your tasks, and not let them run unattended in a fire-and-forget fashion.
When the caller does not await immediately the returned task, and the task was not in a completed state upon creation, you introduce concurrency in your application: More than one things might be happening at overlapping time spans. You can read about the differences between concurrency and parallelism here.
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 4 months ago.
I have a wrapper over Microsoft.Azure.Cosmos.Container class.
In some cases the only thing the wrapper does is calling the inner object's async method.
public Task<ItemResponse<T>> UpsertItemAsync<T>(T item, PartitionKey? partitionKey = null, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default)
{
return _container.UpsertItemAsync<T>(item, partitionKey, requestOptions, cancellationToken);
}
What is the best practice in this case? To add await before or to return the inner object task as is?
David Fowler (ASP.NET Architect) has an excellent guidance.
I copy here the relevant part:
Prefer async/await over directly returning Task
There are benefits to using the async/await keyword instead of directly returning the Task:
Asynchronous and synchronous exceptions are normalized to always be asynchronous.
The code is easier to modify (consider adding a using, for example).
Diagnostics of asynchronous methods are easier (debugging hangs etc).
Exceptions thrown will be automatically wrapped in the returned Task instead of surprising the caller with an actual exception.
❌ BAD This example directly returns the Task to the caller.
public Task<int> DoSomethingAsync()
{
return CallDependencyAsync();
}
✅ GOOD This examples uses async/await instead of directly returning the Task.
public async Task<int> DoSomethingAsync()
{
return await CallDependencyAsync();
}
💡NOTE: There are performance considerations when using an async state machine over directly returning the Task. It's always faster to directly return the Task since it does less work but you end up changing the behavior and potentially losing some of the benefits of the async state machine.
It depends on what you want to achieve.
Here are the 2 case.
If you add an await in this wrapper function - The control stops there waiting for upsert to finish. Once everything is done then control came back to from where this wrapper methord is called
If you ignore an await - Now what happens is this control never wait to execute. It add's that async function to a thread pool using TPL which essentially runs it in background. But you never notice and the code never waits. It continues execution and immediately get back to where you called
2 things to note
If you await it, That line will return the Task result which can be
int, bool, string or whatever
If you ignore await, That line will
return a Task instead
There are many use cases for these 2 approaches.
If your caller requires output to continue, Use await here
If your
caller just calls it and can continue (Not dependent on this upsert,
Let it run in background) then don't use await
You have to add async to your wrapper declaration and await your inner object Task.. otherwise you will not be able to await your wrapper later in a caller context..
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 5 years ago.
See question title.
In other words, given a method
async Task FrobnicateAsync() { ... }
is there any (maybe subtle) difference between
async Task FrobAndFrobnicateAsync()
{
Frob();
await FrobnicateAsync();
}
and
Task FrobAndFrobnicateAsync()
{
Frob();
return FrobnicateAsync();
}
I have a blog post on eliding async.
Since you have a non-trivial Frob before the await, I recommend that you keep the async and await. The benefits of this approach are:
If there is no async and Frob throws an exception, then the exception is thrown directly, which is surprising behavior for the consumers. Even if Frob doesn't throw an exception today, it can do so next year; thus the code with await is more maintainable.
If there is no async, then Frob does not exist in the same logical call context as FrobnicateAsync (assuming it is actually async); instead, it would exist in the same logical call context as the caller of FrobAndFrobnicateAsync. This is not a concern in most code.
Also see What Is the Purpose of return await?
If you literally have the code shown, then you should prefer the return FrobnicateAsync() version - it avoids an extra layer of state machine abstraction and is simply more efficient.
If you have additional things - in particular any finally (including using) code that surrounds the return, then you must be sure to use the await version so that the finally code doesn't happen until after the async task has completed.
If in doubt, use the async/await version.
The good news is: it doesn't impact the signature (so is not a breaking change) to switch between them, so you can implement it the more efficient way now, and change to async/await if you find that you need to add a using block later.
As an additional thought: if you usually expect it to be completed synchronously, you can be more subtle:
Task FrobAndFrobnicateAsync()
{
async Task Awaited(Task t) => await t;
Frob();
var task = FrobnicateAsync();
// in .NET vFuture there will be a task.IsCompletedSuccessfully
return task.State == TaskState.RanToCompletion ? task : Awaited(task);
}
This avoids the state machine when not needed.
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 2 years ago.
Only the last line of the method below is using 'await', just before the method returns, so doesn't this mean that method is basically synchronous and should just be called "Get()" without the async modifier and the suffix Async?
public virtual async Task<TEntity> GetAsync(Guid id)
{
// some more code here
return await _dbSet.FindAsync(id);
}
doesn't this mean that method is basically synchronous
No. It's asynchronous. You're probably thinking of sequential (progressing from one thing to the next), not synchronous (blocking the current thread). An await will pause the method (sequentially) but not block the thread (asynchronously). For more information, see my async intro.
without the async modifier
While you could elide the async/await keywords, I would recommend that you do not. This is because // some more code here may throw an exception. I cover this and other considerations in my blog post on eliding async and await.
and the suffix Async?
No, that suffix is appropriate for any method that returns an awaitable (e.g., Task). So, even if you elide the async and await, it's still returning a task that should be awaited, so it should still have the Async suffix.
You can think of it this way: the Async suffix is part of the API interface. The async keyword is an implementation detail. They often go together, but not always.
Its a matter of opinion. Generally the naming convention is anything that returns Task or Task<T> has a suffix of Async.
Your example above though would be better written like this so you do not have the extra overhead of the async wrapper. This is because you do not need to await the result in that method. The consumer of the method would then await the result if it used it directly.
public virtual Task<TEntity> GetAsync(Guid id, params Expression<Func<TEntity, object>>[] includeProperties))
{
// some more code here
return _dbSet.FindAsync(id);
}
await doesn't block. It awaits asynchronously for an operation to complete. That means that the original thread is released while awaiting. In a desktop application, this means that the UI thread is released while waiting eg for an HTTP or database call to finish.
When that operation completes, execution is returned to the original thread (for desktop applications).
As it is, you can simplify your code by removing the async and await keywords and returning the Task immediatelly. The code doesn't do anything with the results of the operation, so it doesn't need to await for it to finish. This will be done by the caller of the method:
public virtual Task<TEntity> GetAsync(Guid id)
{
// some more code here
return _dbSet.FindAsync(id);
}
The real asynchronous operation in this code is FindAsync. The async keyword is just syntactic sugar that allows you to use the await keyword. If you don't need to await, you don't need the async keyword either
There are many cases where suffixing every async method with Async is simply redundant. If your method returns a Task or Task<T>, and its purpose is to get data from a database or another network resource, then of course it runs asynchronously. The compiler will also almost always give you an error if you forget to await something. With that in mind, there are some good reasons to suffix async methods with Async:
The method runs asynchronously but does not return a Task
There is an alternative other method by the same name that runs synchronously
Forgetting an await in calling code is unlikely to be caught by the compiler
Suffixing a method name with Async is meant to indicate that the method runs asynchronously, which this method does. Whether it does so using async/await or directly returns another Task is an implementation detail. Imagine you were reviewing some code calling the method that forgets to use await. Which of these makes the error more apparent?
var item1 = _example.Get(itemId1);
var item2 = _example.GetAsync(itemId2);
Based on nothing else, there's no reason to believe there's anything wrong with the first line. The second line will at least raise some eyebrows.
I have a method that returns a List<> of an object. This method takes a while to run.
private List<MyObject> GetBigList()
{
... slow stuff
}
This method is called from 4 or 5 sources. So, I thought I would try and use async and await to keep things moving while this list builds. I added this method:
public async Task<List<MyObject>> GetBigListAsync()
{
var resultsTask = GetBigList();
var resuls = await resultsTask;
return resuls;
}
But, on this line:
var resuls = await resultsTask;
I get this error:
List<MyObject> does not contain a definition for GetAwaiter,
and no extension method 'GetAwaiter' accepting a first argument of type List<MyObject> could be found.
What am I missing?
It seems you're a newbee to async-await. What really helped me to understand what async-await does is the restaurant analogy given by Eric Lippert in this interview. Search somewhere in the middle for async await.
Here he describes that if a cook has to wait for something, instead of doing nothing he starts looking around to see if he can do something else in the meantime.
Async-await is similar. Instead of awaiting for a file to be read, a database query to return, a web page to be downloaded, your thread will go up the callstack to see if any of the callers are not awaiting and performs those statements until he sees an await. Once he sees the await the thread goes up the call stack again to see if one of the callers is not awaiting etc. After a while when the file is read, or the query is finished etc, the statements after the await are performed.
Normally while reading your big list your thread would be very busy instead of idly waiting. It's not certain that ordering another thread to do the stuff would improve the time needed to read your list. Consider measuring both methods.
One reason to use async-await, even if it would lengthen the time
needed to read the big list, would be to keep the caller (user
interface?) responsive.
To make your function async, you should do the following:
Declare the function async;
Instead of TResult return Task<TResult> and instead of void return Task;
If your function calls other async functions, consider remembering the returned task instead of await, do other useful stuff you need to do and await the task when you need the result;
If you really want to let another thread do the busy stuff. call
Task.Run( () => GetBigList())
and await when you need the results.
private async Task<List<MyObject>> GetBigListAsync()
{
var myTask = Task.Run( () => GetBigList());
// your thread is free to do other useful stuff right nw
DoOtherUsefulStuff();
// after a while you need the result, await for myTask:
List<MyObject> result = await myTask;
// you can now use the results of loading:
ProcessResult(result);
return result;
}
Once again: if you have nothing useful to do while the other thread is loading the List (like keeping UI responsive), don't do this, or at least measure if you are faster.
Other articles that helped me understanding async-await were
- Async await, by the ever so helpful Stephen Cleary,
- and a bit more advanced: Async-Wait best practices.
resultTask is just the list returned from GetBigList(), so nothing will happen async there.
What you can do is offload the task to a separate thread on the threadpool by using Task.Run and return the awaitable Task object:
// Bad code
public Task<List<MyObject>> GetBigListAsync()
{
return Task.Run(() => GetBigList());
}
While above example best matches what you were trying to do, it is not best practice. Try to make the GetBigList() async by nature or if there really is no way, leave the decision about executing the code on a separate thread to the calling code and don't hide this in the implementation F.e. if the calling code already runs async, there is no reason to spawn yet another thread. This article describes this in more detail.
A couple of years later but I feel it is worth to add for the collection, once people search for the resolution since .NET has changed quite a bit:
return await Task.FromResult(GetBigList())