Another reason to use async await instead of simply returning is that you can get very sudden bugs. (with IDisposable for example) The code below Will crash, because the DbContext will be disposed before the task actually returns. Task GetUsers() { using var ctx = new DbContext(); return ctx.Users.ToArrayAsync(); }
I only directly return a Task if the method contains only one or two lines (ie. is a relaying method). As soon as the method has more things to do to do its job, I do use async await (and have my team do it as well). This video does give an interesting understanding about how things work under the hood. As of now, i'll also consider whether or not i would want a method to be included in stack traces 🙂 So thanks a lot for this insightful video 👍🏻
I also prefer returning CompletedTask in overrides running completely sync instead of marking method async and behave like void. Rider doesn't like when you don't await anything in async method, and I don't like when Rider isn't happy).
There are stupidly edge cases where you actually need to worry about this, but must people won’t ever encounter then, I was once hired to improve some serializers performance so I did care about this, but even I have to admit this had the smallest impact of everything I did
Unfortunately, I can't fully agree with you on this one. The async state machine that you talked about has two different modes. In Debug mode (i.e. code is not optimized), it will be effectively a reference type (mainly to provide better debugging support). In Release mode however, the state machine type will be a struct. It behaves like the following: 1) when the async method is called, the struct will get initialized and MoveNext will be called on it for the first time. This will usually result in an async operation being started. 2) when this async operation completes immediately, the state machine will return the result and set itself to state finished (I think -2 is the corresponding state indicator). The generated state machine itself will never be put on the managed heap in this scenario. This is what you actually measured in your benchmarks. 3) only if the async operation does not complete immediately (which is the expected default behavior of I/O operations), the state machine will be boxed and afterwards resides on the managed heap. Once the async operation signals that it completed, MoveNext will be called again on the state machine. The problem is that the more async methods you have in the call chain, the more state machines will be placed on the managed heap. In usual scenarios, this might be negligible, but devs should keep this in mind. Maybe you can do a memory benchmark on this in a future video? Where you actually determine the size of a state machine in managed heap with DotMemory?
This is 100% true but the video assumes that we are only talking about the Release version of the code, which is also what the benchmark is running on. All the timings and the memory collection and GC invocations are running under Release mode. So the observed memory and speed discrepancy is based on the optimized release version.
@@nickchapsas Yeah, but that's not what I'm complaining about. In your benchmark at the beginning, you return a completed task, or await it, respectively. The async state machine will never be boxed in this case. If you would use a task that is not completed, then you would see additional memory allocations in the method that is marked as async (and it will take longer to run, I suspect at least some microseconds). The basic statement "it only takes 20ns longer and allocates a few more bytes" is problematic.
@@IAmFeO2x Oh I see what you mean. Well observing that and showing it in a benchmark will be really hard to the point where you won't know if it's actually the state machine itself or a discrepancy within margin of error. Take the example at the end of this video for example. Even if the boxing makes it worse, it really is not observable (with an individual isolated use-case) and falls under my "Don't worry about it unless it becomes the next obvious thing to optimise".
@@IAmFeO2x No no it's great that ou mention it because I actually have a video on boxing that I'm working on and I might actually include this point. Thanks!
Yet another great video! Thanks for that, it really helps me understand the matter more deeply and actually be able to talk to my seniors about those topics! 😆
Thank you! Instead of arguing, why there is no meaning in the theoretical speed advantage of returning task (and sacrifice the Debugger) rather then await it -in the context of an app-, I'll just share your Video and take a Coffee.
Seriously man...!!! i'm one of those guys who omits await whenever i can... I didnot realize how stupid this was until now..! This was super super helpful, thanks a lot...!
Nick, I love how you get under the hood of things-- checking the IL and so on. I've not only learned specific ideas from you, but improved my general ability to investigate C# code. But question-- in what universe will today's investigation matter in live code? Are you going to be awaiting 50,000 async tasks with the All modifier?
I've never actually heard advice either way on this before but I followed the same reasoning myself that omitting the async await if possible should be quite a bit faster. Good to see that I was technically right but that the difference is so marginal that it doesn't matter for all but the hottest of hot paths.
Great video! I've been thoroughly enjoying all your videos, from the REST API tutorials to tips and tracks to these benchmarks. I think they all cover very useful topics in very useful ways. :)
Besides the godlike content you provide. I also enjoy your thumbnails. You look like you have a lot of fun doing them. Recommended you to my entire c# colleagues.
So, there is like 1 more difference not mentioned in this video. It's when you introduce a bug into the code because the place where you remove await is using an IDisposable like: public -async- Task Example() { using(var disposable = GetDisposable()) { return -await- disposable.SomethingAsync(); } } When you omit the await, the disposable will be disposed when you await it in a calling function.
I was concerned that you'd profiled this with a completed task, since there's short-circuits in the state machine for a completed task, but that last example was pretty compelling. Interesting results, thanks.
Yeah so the original example uses a pre-computed task because it demonstrates raw state machine-based performance degradation, which is the point that people who say "don't use async await" make. Last example demonstrates a realistic scenario while still keeping all the calculation in memory, meaning that if it was an actual IO call, it would be even less visible.
@Nick Chapsas In my experience, a Program that returns void does not wait for an await method to complete. The void Program is calling the await method and just returning immediately, so I think that last benchmark is flawed. You would need to compare two different programs. One Task Program calling an async Task method, and a void Program calling a Task method.
BenchmarkDotnet has built in behaviour to turn asynchronous when it detects an awaitable task as a benchmark. It’s not an async void and it won’t be treated like an event.
Man, I remember losing hours during a diagnose because the stack trace wasn't showing the correct call chain. Only reason I wouldn't use async\await is if there's a strong argument for a specific scenario.
Recent scenario I had with downloading image from an outside url rececieved in api order payload. My api response was up to 5+ seconds when using await to confirm image save was successful in my api response. Other option is to use a callback to check if image was ok or not while removing the await. This allows for an instant response from order api, but then i cant immediately confirm back if image was good. My callback flags order afterwards if image was bad. Customer is later notified instead of immediately. In this case, it all comes down to how soon you need to know and-or notify end user. Regardless, I almost always use await as it makes life much easier, and has much less lag when not working with images.
i would've loved if the video also showed a usecase where you wouldnt use async to make the nuance more clear vs the only text. edit: indo get the difference remarkn s for a general video improvement
Nice video, but I want to ask something else: forward methods? Is this some concept close to delegation/indirection and the like? Some wrapper object offloading the work to some other? Or is it something more?
Interesting outcome. still getting my head around async/await stuff. As for Benchmarkdotnet, I tried that at work but the work AV stopped it from working :(
I figure BenchmarkDotNet might not be the tool for returning results on this, but I would also expect that not async awaiting the task could also lock up the thread, and if so that'd definitely add time on processing when you're starting to look at network latency effects (which are almost certainly going to be in the order of at least milliseconds). I might be wrong, but I've always understood that being one of the reasons for calling it in that way.
This isn’t the case because the state machine isn’t actually needed there. The method will be awaited and the actual state machine that does the work (the one in the httpclient method) will be honoured. This does not affect behaviour in any and is purely performance and call stack.
Hey Nick thanks for the video. David's list of guidelines also have "Avoid using Task.Run for long running work that blocks the thread" can you talk about this in a future video? He is using the Thread class in his example but to quote Stephen Cleary's book "As soon as you type new Thread() , it's over; your project already has legacy code" What are your thoughts on this? Also in David's example of 'good code' what would be the right course if ProcessItem() method is async. Follow the same guideline?
@@IvarDaigon I still don't think you understand what this is about. There is nothing about Task.Run here. The Tasks in both cases are properly awaited. The difference is tha in one of the cases it's more efficient because the state machine isn't generated for the forward methods, (because it isn't needed). The code will work on a functional level exactly the same. I highy recommend you recreate the code locally and take a look.
It is so good hat somebody does benchmarks you always wanted to make, but too lazy to really do it). What you think about ValueTasks do you find them useful? I think that things that really need some heavy parallel processing should go on lower level working with threads and synchronization primitives, and business logic should go with Tasks focusing on logic and never even thinking about should I await this Task or return as is, or should I use ValueTask here. Your research has broken my last doubts about stoping wasting my time paying attention to such microoptimizations.
I like the debugging vs performance argument. But I am wondering what the impact of building and disposing of a Task is. Probably also not a lot. But still nice to know. And: If you're going to use it synchronously, why use a Task?
The reason I asked is that I have seen it go wrong. And I mean very wrong. A colleague got hung up on the importance of task and async without knowing what multithreading is about. So he ended up writing everything as tasks and awaiting all of it....to build an application that was entirely synchronized. He didn't even bother writing sync versions of anything, so in that project I got stuck using the same style of programming, that I (as a 25 year veteran who had written multithreaded programs the hard way) consider crackpot. By the time I joined the project he had made so much, it was not feasable to refactor... And since then I have seen many examples just like that. This was around the time that async and await were introduced. So there were many people saying how good and important it was. And it IS important, IF you know about multithreading. But if you don't, there's no telling how important because you don't know the why. And of course, many of the examples found around the web didn't help either. Because they showed how to use the things. And what they did. But mostly in demonstration scenarios that don't show the why. So, why use task and async when all of it is immediately synchronized again?
@@frankroos1167 I mean Task and Threading are different topics. They are kinda linked but asynchronous and parallelism are completely different discussions. It sounds like there is a lack of understanding to differentiate the two there.
Interesting topic, but you forgot one more thing ;) In .Net core WebApi count of threads available from pool is limited, and with await they will be available for re-use earlier.
There isn't any threading involved here. The behavior in code is exactly the same as if async was there. The Task will be delegated and it will be awaited downstream without allocating more threads.
@@nickchapsasNope, the thread will be released later in one case. It will be released anyway, yes, but later. So in high load app it will lead to delayed processing of input request
I agree 100%. I literally had to refactor async into .net core api to increase load testing perfomance, the dev who wrote that was under the impression using async makes no difference
You only use async for stuff that is I/O bound, your http request took at least 50 ms and allocated A LOT more than 70 bytes. The async await overhead thus disappears into nothingness anyway.
I've had this argument too many times at work. Stop trying to save nanoseconds. It's just like those car improvement nutcases that remove bits of metal from the car instead of just having a diet.
Also: If 20 nanoseconds are really a problem for you, then C# is probably not the right language for the job. C or Assembly would probably be a better pick haha
Gotta be very, very careful with async/await and Tasks. If you sway from the recommended approaches even a bit you will get unexplained crashes and issues that are impossible to debug. Rule of thumb: always use async/await with Tasks. Also people need to know why they are using async/await and why it exists. What benefits it brings. Why did Microsoft take their time to develop this crazy and complicated technology? Most people use it as if their program were completely synchronous and thus don't see too much direct benefit. They don't think about batching lengthy unrelated processes or other cool tricks you can do that would otherwise require spinning up a new thread. Or what benefits it brings to the web server.
Your examples are overly simplified. In the real world, the await is not slow because of state machine but because of context switching. We run online services which have many simultaneous clients sending short requests and whenever the code executes await, it risks losing its thread, because system decides to use it for some other task. Then the execution without redundant await commands is faster. And especially in .NET Framework in case you need to return to your original thread.
Another reason to use async await instead of simply returning is that you can get very sudden bugs. (with IDisposable for example)
The code below Will crash, because the DbContext will be disposed before the task actually returns.
Task GetUsers()
{
using var ctx = new DbContext();
return ctx.Users.ToArrayAsync();
}
This is actually a very good point! Thanks for pointing it out.
How will it get disposed earlier. Dont understand
@@EMWMIKE this might be only when function called without await. This is wrong example.
@@EMWMIKE when using the “using” keyword
in a code block , after that block the variable is garbage collected i think
@@nickchapsas at 8:31 you pointed to the post, where it was already written :) "consider adding a using, for example"
I only directly return a Task if the method contains only one or two lines (ie. is a relaying method).
As soon as the method has more things to do to do its job, I do use async await (and have my team do it as well).
This video does give an interesting understanding about how things work under the hood. As of now, i'll also consider whether or not i would want a method to be included in stack traces 🙂
So thanks a lot for this insightful video 👍🏻
I also prefer returning CompletedTask in overrides running completely sync instead of marking method async and behave like void. Rider doesn't like when you don't await anything in async method, and I don't like when Rider isn't happy).
Interesting results. Love these benchmarking videos.
I was expecting a 2014 year video, amazing that only now we are getting good content on this stuff. Video very good, thanks.
There are stupidly edge cases where you actually need to worry about this, but must people won’t ever encounter then, I was once hired to improve some serializers performance so I did care about this, but even I have to admit this had the smallest impact of everything I did
true dude.
Good video. I saw people in my team using try catch on a return task and not understanding why they dont hit the catch block
Content factory.☺️
Better than best.☺️
Unfortunately, I can't fully agree with you on this one.
The async state machine that you talked about has two different modes. In Debug mode (i.e. code is not optimized), it will be effectively a reference type (mainly to provide better debugging support). In Release mode however, the state machine type will be a struct. It behaves like the following:
1) when the async method is called, the struct will get initialized and MoveNext will be called on it for the first time. This will usually result in an async operation being started.
2) when this async operation completes immediately, the state machine will return the result and set itself to state finished (I think -2 is the corresponding state indicator). The generated state machine itself will never be put on the managed heap in this scenario. This is what you actually measured in your benchmarks.
3) only if the async operation does not complete immediately (which is the expected default behavior of I/O operations), the state machine will be boxed and afterwards resides on the managed heap. Once the async operation signals that it completed, MoveNext will be called again on the state machine.
The problem is that the more async methods you have in the call chain, the more state machines will be placed on the managed heap. In usual scenarios, this might be negligible, but devs should keep this in mind.
Maybe you can do a memory benchmark on this in a future video? Where you actually determine the size of a state machine in managed heap with DotMemory?
This is 100% true but the video assumes that we are only talking about the Release version of the code, which is also what the benchmark is running on. All the timings and the memory collection and GC invocations are running under Release mode. So the observed memory and speed discrepancy is based on the optimized release version.
@@nickchapsas Yeah, but that's not what I'm complaining about. In your benchmark at the beginning, you return a completed task, or await it, respectively. The async state machine will never be boxed in this case. If you would use a task that is not completed, then you would see additional memory allocations in the method that is marked as async (and it will take longer to run, I suspect at least some microseconds). The basic statement "it only takes 20ns longer and allocates a few more bytes" is problematic.
@@IAmFeO2x Oh I see what you mean. Well observing that and showing it in a benchmark will be really hard to the point where you won't know if it's actually the state machine itself or a discrepancy within margin of error. Take the example at the end of this video for example. Even if the boxing makes it worse, it really is not observable (with an individual isolated use-case) and falls under my "Don't worry about it unless it becomes the next obvious thing to optimise".
@@nickchapsas yeah, I agree with you. Just wanted to point it out.
@@IAmFeO2x No no it's great that ou mention it because I actually have a video on boxing that I'm working on and I might actually include this point. Thanks!
Yet another great video! Thanks for that, it really helps me understand the matter more deeply and actually be able to talk to my seniors about those topics! 😆
Thank you!
Instead of arguing, why there is no meaning in the theoretical speed advantage of returning task (and sacrifice the Debugger) rather then await it -in the context of an app-, I'll just share your Video and take a Coffee.
Seriously man...!!! i'm one of those guys who omits await whenever i can... I didnot realize how stupid this was until now..! This was super super helpful, thanks a lot...!
Nick, I love how you get under the hood of things-- checking the IL and so on. I've not only learned specific ideas from you, but improved my general ability to investigate C# code. But question-- in what universe will today's investigation matter in live code? Are you going to be awaiting 50,000 async tasks with the All modifier?
I've never actually heard advice either way on this before but I followed the same reasoning myself that omitting the async await if possible should be quite a bit faster. Good to see that I was technically right but that the difference is so marginal that it doesn't matter for all but the hottest of hot paths.
Cool. Makes more sense to me now.
Especially after some typescript coding, where awaiting return is pointless.
Thank u, good video as always!
Amazing videos! I love learning these very specific topics!
Could you maybe cover DateTime vs DateTimeOffset?
Nothing new but very nice to see benchmarks to prove the point. Thanks
Great video! I've been thoroughly enjoying all your videos, from the REST API tutorials to tips and tracks to these benchmarks. I think they all cover very useful topics in very useful ways. :)
been wondering about this for a while, now I know for sure. great content man
Γεια σου ρε Νίκο. Φοβερή δουλειά συνέχισε δυνατά.
Besides the godlike content you provide. I also enjoy your thumbnails. You look like you have a lot of fun doing them. Recommended you to my entire c# colleagues.
Nice video. I love this benchmarking videos.
So, there is like 1 more difference not mentioned in this video. It's when you introduce a bug into the code because the place where you remove await is using an IDisposable
like:
public -async- Task Example()
{
using(var disposable = GetDisposable())
{
return -await- disposable.SomethingAsync();
}
}
When you omit the await, the disposable will be disposed when you await it in a calling function.
You are right I wanted to add this in the video but forgot!
Do you do mentorships? You are awesome!
I was concerned that you'd profiled this with a completed task, since there's short-circuits in the state machine for a completed task, but that last example was pretty compelling.
Interesting results, thanks.
Yeah so the original example uses a pre-computed task because it demonstrates raw state machine-based performance degradation, which is the point that people who say "don't use async await" make. Last example demonstrates a realistic scenario while still keeping all the calculation in memory, meaning that if it was an actual IO call, it would be even less visible.
@Nick Chapsas In my experience, a Program that returns void does not wait for an await method to complete. The void Program is calling the await method and just returning immediately, so I think that last benchmark is flawed. You would need to compare two different programs. One Task Program calling an async Task method, and a void Program calling a Task method.
BenchmarkDotnet has built in behaviour to turn asynchronous when it detects an awaitable task as a benchmark. It’s not an async void and it won’t be treated like an event.
This stuff matters with async sequences or fast async while loops. There are many other differences, and we haven’t yet started on ValueTask…
Great video, thank you!
BTW, it will be interesting to have Fody weaver for it - in this case you can switch between return task or use await))
Man, I remember losing hours during a diagnose because the stack trace wasn't showing the correct call chain. Only reason I wouldn't use async\await is if there's a strong argument for a specific scenario.
Thank you!
you make such good content
Great video! Is there any concerns why this approach shouldn't be used in private methods?
I got something new here. Thanks
Recent scenario I had with downloading image from an outside url rececieved in api order payload. My api response was up to 5+ seconds when using await to confirm image save was successful in my api response. Other option is to use a callback to check if image was ok or not while removing the await. This allows for an instant response from order api, but then i cant immediately confirm back if image was good. My callback flags order afterwards if image was bad. Customer is later notified instead of immediately. In this case, it all comes down to how soon you need to know and-or notify end user. Regardless, I almost always use await as it makes life much easier, and has much less lag when not working with images.
i would've loved if the video also showed a usecase where you wouldnt use async to make the nuance more clear vs the only text.
edit: indo get the difference remarkn s for a general video improvement
Great video, thanks!
Thanks for the video. Can you explain async/await state machine. It would be an awesome video.
Nice video, but I want to ask something else: forward methods? Is this some concept close to delegation/indirection and the like? Some wrapper object offloading the work to some other? Or is it something more?
Amazing.. thanks
Interesting outcome. still getting my head around async/await stuff. As for Benchmarkdotnet, I tried that at work but the work AV stopped it from working :(
I've been searching for this like everywhere. This is so confusing!
I figure BenchmarkDotNet might not be the tool for returning results on this, but I would also expect that not async awaiting the task could also lock up the thread, and if so that'd definitely add time on processing when you're starting to look at network latency effects (which are almost certainly going to be in the order of at least milliseconds). I might be wrong, but I've always understood that being one of the reasons for calling it in that way.
This isn’t the case because the state machine isn’t actually needed there. The method will be awaited and the actual state machine that does the work (the one in the httpclient method) will be honoured. This does not affect behaviour in any and is purely performance and call stack.
@@nickchapsas Thank you for clarifying.
Thanks, It will definitely help me for complex Method!
One Q. You know about NopCommerce ?
Nice 😊...love it
Hey Nick thanks for the video.
David's list of guidelines also have "Avoid using Task.Run for long running work that blocks the thread" can you talk about this in a future video? He is using the Thread class in his example but to quote Stephen Cleary's book "As soon as you type new Thread() , it's over; your project already has legacy code"
What are your thoughts on this? Also in David's example of 'good code' what would be the right course if ProcessItem() method is async. Follow the same guideline?
I think I actually address this in a video I made a while ago about David's guidelines: ruclips.net/video/lQu-eBIIh-w/видео.html
@@nickchapsas Thanks nick. I don't think this particular guideline is mentioned in your video, but I'll give it another watch anyway 😊
@@IvarDaigon I still don't think you understand what this is about. There is nothing about Task.Run here. The Tasks in both cases are properly awaited. The difference is tha in one of the cases it's more efficient because the state machine isn't generated for the forward methods, (because it isn't needed). The code will work on a functional level exactly the same. I highy recommend you recreate the code locally and take a look.
Thanks man
Well now i have to ask, what is a forward method?
A forward method is a method that all it really does is expose another method from something that the class has access to
It is so good hat somebody does benchmarks you always wanted to make, but too lazy to really do it). What you think about ValueTasks do you find them useful? I think that things that really need some heavy parallel processing should go on lower level working with threads and synchronization primitives, and business logic should go with Tasks focusing on logic and never even thinking about should I await this Task or return as is, or should I use ValueTask here. Your research has broken my last doubts about stoping wasting my time paying attention to such microoptimizations.
There is a ValueTask video scheduled for next Monday, in which I explain how you can use ValueTask to get some nice memory wins.
9:29 There is an error in IF condition/statements.
So, technically, SerializeAsyncNoAwait should be still faster =)
Cool video!
Interesting 🎉
I would be wary if you had a synchronization context that would be need to use `.ConfigureAwait(false)`
Which theme and/or color scheme are you using in Rider? tks
I actually have no idea. I think I might have made this one years ago after the VS dark theme
Can you do a video on spin lock vs spin wait vs lock
I like the debugging vs performance argument. But I am wondering what the impact of building and disposing of a Task is. Probably also not a lot. But still nice to know.
And: If you're going to use it synchronously, why use a Task?
A Task without they async keyword is still asyncrhonous as long as it is awaited at some point during the pipeline.
The reason I asked is that I have seen it go wrong. And I mean very wrong. A colleague got hung up on the importance of task and async without knowing what multithreading is about. So he ended up writing everything as tasks and awaiting all of it....to build an application that was entirely synchronized. He didn't even bother writing sync versions of anything, so in that project I got stuck using the same style of programming, that I (as a 25 year veteran who had written multithreaded programs the hard way) consider crackpot. By the time I joined the project he had made so much, it was not feasable to refactor...
And since then I have seen many examples just like that.
This was around the time that async and await were introduced. So there were many people saying how good and important it was. And it IS important, IF you know about multithreading. But if you don't, there's no telling how important because you don't know the why.
And of course, many of the examples found around the web didn't help either. Because they showed how to use the things. And what they did. But mostly in demonstration scenarios that don't show the why.
So, why use task and async when all of it is immediately synchronized again?
@@frankroos1167 I mean Task and Threading are different topics. They are kinda linked but asynchronous and parallelism are completely different discussions. It sounds like there is a lack of understanding to differentiate the two there.
@@nickchapsas I see your point. I'll wait for a video on it. Because it is still an interesting topic.
Before watching comment: my understanding is that the runtime/compiler kinda handles any redundant awaits so both styles have the same behavior
This comment is awesome because it shows that there was a need for this video
Wish there would be a benchmark comparison with ValueTask’s hot path.
8th of April is the scheduled release date for the ValueTask video
Interesting topic, but you forgot one more thing ;) In .Net core WebApi count of threads available from pool is limited, and with await they will be available for re-use earlier.
There isn't any threading involved here. The behavior in code is exactly the same as if async was there. The Task will be delegated and it will be awaited downstream without allocating more threads.
@@nickchapsasNope, the thread will be released later in one case. It will be released anyway, yes, but later. So in high load app it will lead to delayed processing of input request
I agree 100%. I literally had to refactor async into .net core api to increase load testing perfomance, the dev who wrote that was under the impression using async makes no difference
Nick is correct here, there is no practical behavior difference as there is no code following the final await, so there's no continuation to schedule
I think is better to use Task.Delay in benchmark
It is actually note because Task.Delay isn’t guaranteed to be precise
You only use async for stuff that is I/O bound, your http request took at least 50 ms and allocated A LOT more than 70 bytes. The async await overhead thus disappears into nothingness anyway.
My database requests in production take less than 1 ms
I've had this argument too many times at work.
Stop trying to save nanoseconds.
It's just like those car improvement nutcases that remove bits of metal from the car instead of just having a diet.
Also: If 20 nanoseconds are really a problem for you, then C# is probably not the right language for the job. C or Assembly would probably be a better pick haha
So, basically, wrapping the call inside a try/catch would have achieved the same… without all the state machinery.
Estaria padre un canal en español
Anyone could get me the David's article he mentions?
github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md
@@nickchapsas Thank you
RUclips is a developer's nightmare - everyone wants to do videos instead of good ol articles which you can skim in 1 minute :)
Great video but please do not fall for the "Weird face thumbnails are funky" trend. Please?
Seems to be working out great. Need to catch your attention. My metrics say that just text on the thumbnail doesn't cut it :D
@@nickchapsas Yeah you're right. I tried to stop the progress, bu I'll admit it is futile. What is a bug against a giant wave? Food for thought.
Gotta be very, very careful with async/await and Tasks. If you sway from the recommended approaches even a bit you will get unexplained crashes and issues that are impossible to debug. Rule of thumb: always use async/await with Tasks.
Also people need to know why they are using async/await and why it exists. What benefits it brings. Why did Microsoft take their time to develop this crazy and complicated technology? Most people use it as if their program were completely synchronous and thus don't see too much direct benefit. They don't think about batching lengthy unrelated processes or other cool tricks you can do that would otherwise require spinning up a new thread. Or what benefits it brings to the web server.
Your examples are overly simplified. In the real world, the await is not slow because of state machine but because of context switching. We run online services which have many simultaneous clients sending short requests and whenever the code executes await, it risks losing its thread, because system decides to use it for some other task. Then the execution without redundant await commands is faster. And especially in .NET Framework in case you need to return to your original thread.
When using tasks our rule is to always use async Task and await, that prevents any issue of non-awaited calls
Of course it's slower, lol, but that's not the point.