I am trying to make my base repository class asynchronous and I am running into some trouble. I am using Dapper ORM in my C# application.
Base method
protected async Task<List<T>> Read<T>(CommandDefinition cmd) {
using(SqlConnection myCon = new SqlConnection(Config.DBConnection)) {
await myCon.OpenAsync();
IEnumerable<T> results = await myCon.QueryAsync<T>(cmd);
List<T> retVal = results.ToList();
myCon.Close();
return retVal;
}
}
Calling method
public List<Category> GetAllActiveCategories(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result;
}
Everything looks in order to me. I have the method declaration decorated with the async keyword. I am awaiting on asynchronous methods.
The problem that I am having is that the thread blocks on await myCon.OpenAsync();. This is my first attempt at using async and await, so I am sure that I am doing something wrong, but it is not obvious. Please help!
The posted Read code is fine. The issue is in the consuming code. It's common to get a deadlock with async if you call Wait() or Result on the returned Task or its antecedent Task up in the call chain.
As always in these cases, the general advice applies: don't block on async code. Once you start using async/await, you should be using async/await throughout your entire call chain.
So, your calling method becomes
public Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}
... or
public async Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
List<Category> result = await base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
// Do something.
return result;
}
The culprit is:
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result;
As Kirill noted, any time you use .Wait() or .Result on a Task, you are blocking synchronously. What you need to do is this:
public Task<List<Category>> GetAllActiveCategories(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}
This will return a Task to the calling method of this method, and so on... it has to be async "all the way up".
If the top-level consumer of this code is ASP.NET, you're fine. Just return a Task<IActionResult> (or the appropriate return type wrapped in a Task) and the framework will sort out the awaiting for you.
If you're writing a console application or otherwise can't make it "async all the way up", you'll have to either block on .Result or make your method async void and use await. Neither one is a great solution, sadly. Async/await is pretty aggressive in the sense that you really do have to use it throughout your stack.
Related
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.
I've read a bunch of forums, tutorials and blogs talking about the usage of Async/Await in C#. The more I read the more confusing it gets.
Also, people mainly talk about calling async stuff in a sync method but not calling sync stuff in an async method.
As I am a junior developer and do not have much experience with async programming I'll post a new question here and hope for some enlightenment.
Consider this:
I have a Web API endpoint that does some calculations and model building and returns some data.
public async Task<JsonResult> GetData()
{
Task<Data> stuff1Task = CalculateStuff1();
Task<Data> stuff2Task = CalculateStuff2();
Task<Data> stuff3Task = CalculateStuff3();
return Json(
new
{
stuff1 = await stuff1Task,
stuff2 = await stuff2Task,
stuff3 = await stuff3Task
}, JsonRequestBehavior.AllowGet
);
}
private async Task<Data> CalculateStuff1()
{
return await SomeAsyncCalculation();
}
private async Task<Data> CalculateStuff2()
{
return SomeSyncCalculation();
}
private async Task<Data> CalculateStuff3()
{
Task<Data> dataTask1 = SomeAsyncCalculation();
Task<Data> dataTask2 = AnotherAsyncCalculation();
Data data1 = await dataTask1;
Data data2 = await dataTask2;
Data combindedData = SyncMethodToCombineData(data1, data2);
return combindedData;
}
Why I consider mixing async and sync code is for getting better performance.
In this case lets pretend SomeAsyncCalculation(), SomeSyncCalculation() and AnotherAsyncCalculation() are pretty costly methods. My goal is to get the methods to run somewhat in parallel to gain some faster response times.
I know it is best to go "Async all the way" but lets be real, rebuilding half the project is not always a priority or a possibility.
Also I might have some integrations with other systems that do not support async operations.
This warning I get for CalculateStuff2() adds to the confusion. :
this async method lacks 'await' operators and will run synchronously
In my understanding the "async" keyword is only good for wrapping the method and allowing me to use await keyword. It also allows me to just return the data and I don't need to manage Task returning results. It also handles exceptions.
The Task<TResult> return type is what makes the method execute on a different thread (although it is not guaranteed it will execute on a different thread).
Concluding questions:
1. Will the async method that does not use await (CalculateStuff2()) run synchronously on it's own thread (if it runs on another thread because it is a Task) or will it run in the main thread of the API call, and always block it no matter what?
2. Is it bad practice to use async without await just to have a nicely wrapped task method out of the box?
You're not need for async in sync method. async generates State Machine that is a kind of redundancy in case you're not need for await.
Consider this somewhat optimized example.
public async Task<JsonResult> GetData()
{
Task<Data> stuff1Task = CalculateStuff1();
Task<Data> stuff3Task = CalculateStuff3();
Data stuff2data = CalculateStuff2(); // run sync method after launching async ones
return Json(new
{
stuff1 = await stuff1Task,
stuff2 = stuff2data,
stuff3 = await stuff3Task
}, JsonRequestBehavior.AllowGet);
}
private Task<Data> CalculateStuff1() // optimized
{
return SomeAsyncCalculation();
}
private Data CalculateStuff2()
{
return SomeSyncCalculation();
}
private async Task<Data> CalculateStuff3()
{
//use combinator to simplify the code
Data[] data = await Task.WhenAll(SomeAsyncCalculation(), AnotherAsyncCalculation());
Data combindedData = SyncMethodToCombineData(data[0], data[1]);
return combindedData;
}
Also consider to differ the CPU-bound and IO-bound operations, look at this article. There's different async approach depending on what exacly you're launching.
Direct answers
Will the async method that does not use await (CalculateStuff2()) run synchronously on it's own thread (if it runs on another thread because it is a Task) or will it run in the main thread of the API call, and always block it no matter what?
Yes, it will run synchronously on the caller Thread. If you want to run some sync method on its own Thread, use Task.Run():
Task<Data> stuff2Task = Task.Run(() => CalculateStuff2());
and then await it.
Is it bad practice to use async without await just to have a nicely wrapped task method out of the box?
Yes, it's bad practice. Redundant State Machine makes overhead which in this case is worthless.
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
How and when to use ‘async’ and ‘await’
(25 answers)
Closed 3 years ago.
I was looking at how to use async await, but I do not quite get it when we have multiple methods invoking each other. Should we always use await or should we only use await when we are actually ready to use the result?
So for example should we do it like this:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
async Task<string> Func1()
{
return await Func2();
}
async Task<string> Func2()
{
return await tcpClient.ReadStringAsync();
}
Or like this:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
Task<string> Func1()
{
return Func2();
}
Task<string> Func2()
{
return tcpClient.ReadStringAsync();
}
Per example 1, should we always use await in every method?
Or
Per example 2 should we only use await on the top-most method when we start using the result?
Every-time you call await it creates a lump of code to bundle up variables, captures the synchronization context (if applicable) and create a continuation into an IAsyncStateMachine.
Essentially, returning a Task without the async keyword will give you a small run-time efficiency and save you a bunch of CIL. Do note that the Async feature in .NET also has many optimizations already. Also note (and importantly) that returning a Task in a using statement will likely throw an Already Disposed Exception.
You can compare the CIL and plumbing differences here
Forwarded Task
Async Method
So if your method is just forwarding a Task and not wanting anything from it, you could easily just drop the async keyword and return the Task directly.
More-so, there are times when we do more than just forwarding and there is branching involved. This is where, Task.FromResult and Task.CompletedTask come into play to help deal with the logic of what may arise in a method. I.e If you want to give a result (there and then), or return a Task that is completed (respectively).
Lastly, the Async and Await Pattern has subtle differences when dealing with Exceptions. If you are returning a Task, you can use Task.FromException<T> to pop any exception on the the returned Task like an async method would normally do.
Nonsensical example
public Task<int> DoSomethingAsync(int someValue)
{
try
{
if (someValue == 1)
return Task.FromResult(3); // Return a completed task
return MyAsyncMethod(); // Return a task
}
catch (Exception e)
{
return Task.FromException<int>(e); // Place exception on the task
}
}
In short, if you don't quite understand what is going on, just await it; the overhead will be minimal. However, if you understand the subtitles of how to return a task result, a completed task, placing an exception on a task, or just forwarding. You can save your self some CIL and give your code a small performance gain by dropping the async keyword returning a task directly and bypassing the IAsyncStateMachine.
At about this time, I would look up the Stack Overflow user and author Stephen Cleary, and Mr. Parallel Stephen Toub. They have a plethora of blogs and books dedicated solely to the Async and Await Pattern, all the pitfalls, coding etiquette and lots more information you will surely find interesting.
Both options are legit and each option has own scenarios where it is more effective then another.
Of course always use await when you want to handle result of the asynchronous method or handle possible exception in current method
public async Task Execute()
{
try
{
await RunAsync();
}
catch (Exception ex)
{
// Handle thrown exception
}
}
If you don't use result of asynchronous method in current method - return the Task. This approach will delay state machine creation to the caller or where ever final task will be awaited. As pointed in the comments can make execution little bit more effective.
But there are scenarios where you must await for the task, even you do nothing with result and don't want handle possible exceptions
public Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return context.Entities.FindAsync(id);
}
}
In the scenario above, FindAsync can return not completed task and this task will be returned straight away to the caller and dispose context object created within using statement.
Later when caller will "await" for the task exception will be thrown because it will try to use already disposed object(context).
public async Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return await context.Entities.FindAsync(id);
}
}
And traditionally answers about Async Await must include link to Stephen Cleary's blog
Eliding Async and Await
Await is a sequencing feature which allows the caller to receive the result of an async method and do something with it. If you do not need to process the result of an async function, you do not have to await it.
In your example Func1() and Func2() do no process the return values of the called async functions, so it is fine not to await them.
When you use await the code will wait for the async function to finish. This should be done when you need a value from an async function, like this case:
int salary = await CalculateSalary();
...
async Task<int> CalculateSalary()
{
//Start high cpu usage task
...
//End high cpu usage task
return salary;
}
If you hadn't use the the await this would happen:
int salary = CalculateSalary().Result;
...
async Task<int> CalculateSalary()
{
//Start high cpu usage task
... //In some line of code the function finishes returning null because we didn't wait the function to finish
return salary; //This never runs
}
Await means, wait this async function to finish.
Use it to your needs, your case 1 and 2 would produce the same result, as long as you await when you assign the info value the code will be safe.
Source: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index
I believe the 2nd one will do because await is expecting a return value.
Since it is waiting for the Func1() to return a value, Func1() is already executing Func2() which is returning a value.
What is the best practice when returning the following Task:
public async Task<Command> BuildCommunicationCommand
As an object:
public Command BuildCommand
I have the following:
public Command BuildCommand()
{
return BuildCommunicationCommand().GetAwaiter().GetResult();
}
But have been told to try and avoid this and that I should await the Task so we do not block the UI thread. I think the best way to do this is to make the BuildCommand method async and anything else that calls it. This would be a massive change and is not really required for other classes which use the BuildCommand. I do not want to cause a block by using .Result so have read its best to use ConfigureAwait(false) in this case:
public Command BuildCommand()
{
var Command = BuildCommunicationCommand().ConfigureAwait(false);
return Command.GetAwaiter().GetResult();
}
Can I use ConfigureAwait(false) to wait for the process to finish and then call .GetAwaiter().GetResult() to return it as the object Command?
This is my first time working with async tasks so if any of the above is complete rubbish I am sorry!
You can wrap the call to your async method in another method that waits for the task to complete and then returns the result. Of course that blocks the thread that calls GetData. But it gets rid of the async 'virus'. Something like this:
private string GetData()
{
var task = GetDataAsync();
task.Wait();
return task.Result;
}
private async Task<string> GetDataAsync()
{
return "Hello";
}
You're asking after best practices though, and that is to change everything to async as needed.
For example, in the code below, the last method M2Async is synchronous and does not have async/await as otherwise there would need to be a call to M3Async after await and the call graph would continue?
For clarity (from C# in a Nutshell):
A synchronous operation does its work before returning to the caller.
An asynchronous operation does (most or all of) its work after returning to the caller.
public void Main()
{
Task task = M1Async();
// some work
int i = task.result;
// use i etc
}
private async Task M1Async()
{
int i = await M2Async();
// some work
return i;
}
private Task M2Async()
{
return Task.FromResult(2);
}
That depends a bit on what you mean by "synchronous". In some ways, all methods are synchronous (even async ones) - they just synchronously return something that can be awaited and which might have more things to do once awaited.
No, it doesn't have to be synchronous; your code could just as well be:
private async Task<int> M2Async()
{
return await Task.FromResult(2);
}
or even just (although the compiler will detect that this is a smell, and is secretly synchronous):
private async Task<int> M2Async()
{
return 2;
}
Neither of which would be particularly useful, but; they would work. In reality, most async methods will bottom out at something that is doing async IO - file-system, network, etc. In your example, there is nothing that will actually truly be async anyway - it will all be completed when the await is reached.
I have an async method:
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, string language, bool throwEx = true)
{
UserLoginExResult result = await UserService.LoginExAsync(UserGroup, language, TimezoneOffset, GetDeviceInfo(), GetLoginProperties(), exRequest);
ProcessLoginResult(result, false, throwEx);
return result;
}
And an overload:
public Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
return LoginExAsync(exRequest, Language.ID, throwEx);
}
I'm not sure if I should mark the overloaded one (the one with fewer parameters) as async and use await? I guess I should not but can you tell me what whould happen if I would do that? I'm quite lost in here and not really sure what Task it would wait for? Would it create an extra Task or await doesn't create a new Task?
No, there's little benefit in using an async method when it's just going to wrap and unwrap an existing one. It's fine to just have a "normal" method here, delegating to the "real" async method.
(They're not quite the same - for example, if the UserService.LoginExAsync method throws an exception rather than returning a failed task, the async/await version will just return a failed task, whereas the other version will also throw immediately.)
The async keyword only enables the await keyword. In your case, you can return the Task directly, so there's no need for the async keyword. async would only add overhead without adding any value.
For more information, see Stephen Toub's Zen of Async talk. He addresses this situation directly.
It would really only be worth doing if you were doing additional work in your overload, e.g.
public async Task<UserLoginExResult> LoginExAsync(CustomTable exRequest, bool throwEx = true)
{
Task<UserLoginExResult> result = await LoginExAsync(exRequest, Language.ID, throwEx);
//Do some work here that depends on the result from the task completeion
return result;
}
But as you are not, it isn't!
The overload doesn't need to be marked as async as it doesn't internally await anything, so therefore there's nothing for the compiler to rewrite.