I've a stupid question to ask everyone to learn some best practises async return types in c#. I've a method like this:
public virtual async Task OnConnected(WebSocket socket, HttpContext context)
{
string connectionId = CreateConnectionId(context);
ConnectionManager.AddSocket(connectionId, socket);
//Question is here await what ?
}
I'd like to post to improve my application with a best performance with async and await. Pls don't thumb dowm my post. Can everyone suggest for me some resources best practices async return types?
Tks everyone.
If there is nothing to await and this is an overridden method. Just ignore the compiler warning (or pragma is out), and do nothing.
Why do nothing?
Because when you place an async on a method, the compiler automatically places any exception on the task for you.
or you could remove the async and return a completed task
public virtual Task OnConnected(WebSocket socket, HttpContext context)
{
string connectionId = CreateConnectionId(context);
ConnectionManager.AddSocket(connectionId, socket);
return Task.CompletedTask;
}
My advice would be to do the former, (do nothing)
However if you were to go the second approach it would be better to place any exceptions on the returned task just as the async and await pattern would.
public virtual Task OnConnected(WebSocket socket, HttpContext context)
{
try
{
string connectionId = CreateConnectionId(context);
ConnectionManager.AddSocket(connectionId, socket);
// more stuff
return Task.CompletedTask;
}
catch (Exception e)
{
return Task.FromException(e);
}
}
learn some best practises async return types in c#.
The first rule of async is "don't use it unless you need to." The second rule is "start with await, not async".
So this part of the question is incorrect:
//Question is here await what ?
Instead of starting with async and trying to "make the code asynchronous", you should start at the opposite end: identify what is naturally asynchronous (i.e., what you should await) first. You need something to await before making your code asynchronous.
You should use await if you have naturally-asynchronous work to do. This is usually I/O-based, so if you're calling an API or doing a database query, that would be something that can be made asynchronous. Once you identified the low-level I/O call, change the method to call the asynchronous version of that API, and add an await. The compiler will guide you from there, changing the method containing the await to be async and changing its return type from void to Task or T to Task<T>. Then let async/await grow naturally through your codebase.
If you do not have any asynchronous operation to be waited for, then you can make the method as a normal synchronous method. If you are making a method async, then it is good practice to name the method in such a way that it ends with ASYNC like OnConnectedAsync.
Generally you use async/await methods when you have any I/O operations (like file access, web download/upload) that can be done independent of your program logic. Simply put the control flow goes like,
main thread calls the async method to trigger the I/O operation
control is returned to main thread after an await is encountered; usually another thread is allotted to execute remaining statements of the async method
main thread continues to execute its statements until it requires the result of the I/O operation
main thread waits for the result of async method (i.e. result of I/O operation) by calling any wait or GetResult method of Task
once the main thread gets the results, it continues executing its statements
You can go through numerous tutorial videos on youtube on async/await.
Related
I have async methods inside my libraries and the top level call is made at the handler of AWS Lambda functions synchronously (for some reason not to discuss here). I wonder if any calls made down the track be asynchronous by any chance? or because the first caller does it synchronously will everything be synchronous?
public void LambdaHandler(Input inp, ILambdaContext context)
{
method1().GetAwaiter().GetResult();
}
private async Task method1()
{
await method2();
await method3();
}
private async Task method2()
{
//do something
}
private async Task method3()
{
//do something
}
method2 and method3 will do whatever they always have done. If they are purely synchronous behind a Task API, then they will continue to be synchronous; if they are asynchronous, then they will continue to be asynchronous. The only question here is: what will LambdaHandler do, and the answer to that is simply:
it will block until they are complete
If they are already complete synchronously, then fine; if they aren't, then you've tied up a thread in a sync-over-async block. This could by itself cause a deadlock if your code uses a sync-context or task-scheduler that only has a single worker (which isn't uncommon), as the thread that the async code will need to do any post-processing will be stuck waiting at GetResult(). So the async part can't complete, and GetResult() can't complete.
You should avoid sync-over-async like the plague. There is a reason it is considered an anti-pattern.
The methods down below the call stack will run asynchronously.
But the entire thing would block and wait for the task to complete.
The better way is to modify LambdaHandler to return Task and use await instead of calling the GetAwaiter.
Help link
The task API feels sort of like a pit of failure, given how every possible thing I could do with it comes with more DON'T than DO. But I'm trying to use it more, and I'm confused about the entire issue of async void.
My problem happens in a place where my application's used a local data file forever, and because it was fast synchronous calls were used. Now some remote sources are an option, and they have enough latency I'm switching it all to be asynchronous.
So I've got a method that maybe looks like this:
void InitializeData() {
SomeProperty = _dataSource.Load(...);
}
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
But there are SO many articles about how terrible it is to use async void, and they seem to blur with discussion of returning a Task. So is my best option really to write it like:
Task<DataType> FetchDataAsync() {
return _dataSource.LoadAsync(...);
}
...then hunt down all the callers and make them comply?
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await. In this situation, I'm very unlikely to ever be using await. Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
So:
Is "Don't use async void" the same thing as "Don't use Task?
If you don't use await, does it mitigate that?
If you do use await, does always wrapping it with a try/catch mitigate the issue?
async void is not the same as returning a Task. The problem with async void is there is no way to observe task exceptions (other then the global exception handler), and no way to wait for the task to complete (you actually can't await an async void method because there is nothing to await), this is why it should be avoided.
Returning Task does not have these problems, if you await it you know when it completes and you will get exceptions where you await so returning a Task is perfectly acceptable.
It looks like you're just confused. The await/async API is incredibly simple. The only confusing part is understanding the difference between await/async API and the Task API. I won't go into great detail about this as the Stephen Cleary's blog clearly covers this, but here is the important excerpt:
To reiterate a sentence from my last post, use Task.Run to call CPU-bound methods (from GUI threads). Do not use it just to “provide something awaitable for my async method to use”.
next...
The naive thing I want to do for low-friction is:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
This is a clear case of offloading Sync code into a Async wrapper which doesn't really do any good.
But there are SO many articles about how terrible it is to use async void,
This is clearly not a async void method. This is a non-async Task returning method. Here is an async void method:
async void InitializeDataAsync() {
await Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
they seem to blur with discussion of returning a Task.
I've not read anything that blurs this information. It's pretty simple; if you have an async method, always return Task or Task<T> (except as stated below). The difference between using these two (Task or Task<T>) is purely design/architecture.
So is my best option really to write it like:
Best is really an opinion here. Both of these work and don't forget async/wait
async Task<DataType> FetchDataAsync() {
return await _dataSource.LoadAsync(...);
}
async Task FetchDataAsync() {
_data = await _dataSource.LoadAsync(...);
}
I feel like the argument people make is that async void is bad because of the different behavior of async Task and the dreaded UnobservedTaskException when you use await.
The most important difference is how exceptions are handled:
Excerpt:
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started.
So
Or if I do use await, it's always going to have a try/catch around it because we're already paranoid about UnobservedTaskException.
This means that you can't catch an exception by try/catch around async void. That is a huge problem!
Is "Don't use async void" the same thing as "Don't use Task?"
Well this is apples and oranges. Yes: don't use async void unless you're using them for async event handlers.
Don't use Task's unless they are CPU bound or you're using a Framework call (or you've correctly wrapped your own method which uses IO Completion Ports).
If you don't use await, does it mitigate that?
Hopefully by now you understand that await/async is different from a Task, and what you're trying to do is write all await/async code.
If you do use await, does always wrapping it with a try/catch mitigate the issue?
Depends, as stated above.
I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.
Does anybody know what is the purpose of doing this?
private async Task<bool> StoreAsync(TriviaAnswer answer) { ... }
[ResponseType(typeof(TriviaAnswer))]
public async Task<IHttpActionResult> Post(TriviaAnswer answer)
{
var isCorrect = await StoreAsync(answer);
return Ok<bool>(isCorrect);
}
From examining this, it is telling it to run the private method asynchronously but synchronously wait for it to end. My question is, is there any point to this? Or is this just a fancy yet futile technique? I ran into this while studying some code for Web API / MVC / SPA.
Anyway, any insights would be useful.
Despite its name, await doesn't actually work like Thread.Join. async and await are Microsoft's implementation of coroutines, implemented using a Continuation Passing Style. Work is reordered so that processing can continue while the Task<T> is being completed. Instructions are re-arranged by the compiler to make maximum use of the asynchronous operation.
This article explains it thusly:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
For some trivial code examples, await doesn't really make much sense, because there is no other work that you can do in the meantime while you are awaiting.
Lets say im within an ASP.NET application, WCF or web API, part of this applications job to is contact a 3rd party over the way. Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
Here is some code i have written:
public string GetSomeData()
{
Task<string> stuff = CallApiAsync();
return stuff.result; //does this block here?
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
I thought the idea was as follows but please correct any misconceptions.
The caller of CallApi can call the method and when it hits await there is a Task created which represents some work to be done asynchronously but that will take some time. At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request. Once the Task completes the await line wakes up and the code continues from there as if it was synchronous.
If this is the case why do i need to return a Task from my apimethod. The caller seems to have to call stuff.Result which implies that the task may not have finished and calling result could block ? Note i don't want to make the calling method async too as then the method that calls that would need to be async etc etc.
What is the order of event here in my code?
One other question is why did i need to set configureAwait to false? otherwise everything hangs.
Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
That's not possible. In order to be truly asynchronous, you must allow async to "grow" through the code as far as it needs to. What you're trying to do is block on an asynchronous call, which won't give you any benefit (you're freeing up a thread by using async, but then you're turning around and consuming a thread by using Result).
At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request.
Not quite. When an async method hits an await, it returns an incomplete Task to its caller. If the caller, in turn, awaits that task, then it returns an incomplete Task to its caller, etc. When the ASP.NET runtime receives an incomplete Task from your action/service method/whatever, then it releases the thread to the thread pool.
So, you do have to go "async all the way" to see the real benefit of async.
I have an async intro on my blog if you want a more gentle introduction, as well as an MSDN article on async best practices (one of which is: async all the way). I also have a blog post that describes the deadlock you were seeing.
The compiler handles a lot of the magic behind the async pattern for you, but syntactically, you have to tell it what you want it to do by providing a method prototype that says "ok, this is an asynchronous operation that can be awaited."
For this to happen, your method must return a Task or Task<T>.
Any Task can be awaited.
You should be VERY careful when using .Result and .Wait(), as they can block in some very unexpected circumstances, because the runtime may decide to execute your method synchronously.
You should say:
await CallApiAsync();
or, to actually take advantage of it:
Task stuff = CallApiAsync();
//More code that can happen independetly of "stuff"
await stuff;
In order to do that, your GetSomeData() function must also be marked as async, but it doesn't have to, itself, return a Task.
Finished copy of a working async version of your code:
public async string GetSomeData()
{
Task stuff = CallApiAsync();
return await stuff;
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
Honestly, if that's all the CallApiAsync function is ever going to do, you may as well inline it, though.