I am trying to understand async/await and I am wondering if both methods work identically.If not can you explain why?
public async Task
Let me point out a few things with your functions:
public async Task GetClient()
{
return await _clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefaultAsync();
}
This first function is a bit wasteful. Neither async
nor await
are giving you any benefit. Why do I say that? Well let's just quickly recap the usual benefit of await
.
What await
allows you to do is to resume execution of the remainder of the method after the awaited task completes. In your case there is no "remainder of the method" since the return await
is the last statement of the method.
Why is this wasteful? Well, by marking your method async
you are basically telling the compiler to generate all the machinery (i.e. state machine) to allow you to resume execution within that same method after each await.
This machinery is useless in your case since there is nothing after the await to resume executing, so you are better off not marking the method async
and instead of return await
just do a simple return of the task generated by FirstOrDefaultAsync
.
Doing this will still make the function return and behave asynchronous. Keep in mind that async
and await
aren't actually what make a function execute asynchronously. async/await
simply help setup the machinery to provide "bookmarks" into the various await points in your method so that execution can resume there after each awaited task completes.
Now let's talk about your second function:
public Task GetClient2()
{
return Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
}
This function is not asynchronous at all. It will execute completely synchronous and not yield the thread at all.
Even if you did this:
public async Task GetClient2()
{
return await Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
}
The function will still be completely synchronous. Remember, async/await
are all about setting up machinery and bookmarks but don't actually have any role on whether the code will execute synchronously or asynchronously.
So why is this blocking? Because FirstOrDefault()
does not return a task, so it means it has to return a Client
object. This means it can't return anything until it fully completes the execution of the linq
chain. Your Task.FromResult
is then just taking this value and wrapping it in a pre-completed task.
So Just to Recap:
Only use async/await
if you need to resume execution somewhere in the middle of your method.
Example:
public async Task IsIntegerIGetFromRemoteServerPostitiveAsync(){
int result = await GetSomeIntegerAsync();
Console.WriteLine('Resuming execution of the method');
return i>0;
}
If you find that you have a single await and it is the last line of the method then don't use async/await
, just return the task instead of awaiting it. This avoids unnecessary overhead.
Example:
public Task GetUserInformationAsync(string username){
var url = $"http://userinfo.com?username={username}"
return GetSomeJsonFromHttpServerAsync(url); //Assuming this returns Task
}