Why is async void bad and how do I await a Task in an object constructor in C#?

  Рет қаралды 25,743

Brian Lagunas

Brian Lagunas

3 жыл бұрын

In this video, I answer the question "Why is async void bad and how do I await a Task in an object constructor?".
Async void is generally considered bad for 3 reasons:
1. You can’t wait for its completion (fire and forget)
2. Any unhandled exceptions will terminate your process (can't be caught)
3. Difficult to test (see #1 and #2)
Async void methods have different error-handling semantics. When an exception is thrown out of an 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.
However, let's be honest, there are many areas of our code where an async void will be required. The scenario that immediately come to mind is in the constructor of an object. For example, maybe you want to load data async when your object is first created. You want to load your data async, and let the object creation process continue without blocking any threads. This is normally done with what's called a "fire and forget" approach. Other scenarios may include the Execute method of an ICommand, or within an event handler.
Your first instinct may be to wrap these async/await calls into an "async void" method, and then just call that method in your constructor, command, or event handler. But, this is not recommended.
Luckily for use, we can use the power of a C# extension method to provide support for not only handling the completion of a Task in an async void scenario, but also handle any exceptions that may occur and provide better unit testing support.
Check out my new Pluralsight course "Introduction to Prism for WPF":
pluralsight.pxf.io/bE3rB
Sponsor Me:
github.com/sponsors/brianlagunas
Follow Me:
Twitter: / brianlagunas
Twitch: / brianlagunas
Blog: brianlagunas.com
GitHub: github.com/brianlagunas

Пікірлер: 227
@meJevin
@meJevin 3 жыл бұрын
Your channel is extremely underrated. Your production quality is insane and the information I’m getting out of these videos is really useful. Thanks dude!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much for the kind words. It motivates me to create more content.
@MichaelJoe212
@MichaelJoe212 Жыл бұрын
short and to the point & solves problems with quick useful examples instead of long lectures -- channel is very underrated!
@diegoronkkomaki6858
@diegoronkkomaki6858 3 жыл бұрын
Great to-the-point video. I appreciate short videos like this, which teach you something in under 10 minutes as rarely does one have time for ~1h tutorials.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much for the kind words. My goal is to always keep my tutorials to under 15 minutes max.
@VinuP2023
@VinuP2023 3 жыл бұрын
This is super helpful Brian. Please make more of these short and to the point videos. You know what, this video of yours got so much attention and great feedback from your viewers. Thanks much :)
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you for your kinds words sir. Let's make a deal. If you share my videos with everyone you know, I'll create more videos. Deal? 😁
@VinuP2023
@VinuP2023 3 жыл бұрын
@@BrianLagunas Deal 😃😃 I will surely share with people I know in software field
@alexanderkvenvolden4067
@alexanderkvenvolden4067 9 ай бұрын
I like this a lot better than the typical "just don't use async void" advice. I do use a similar method for the "fire and forget" use case that is an async void at the bottom layer, but also has a catch(Exception) and mechanism for handling exceptions.
@BrianLagunas
@BrianLagunas 9 ай бұрын
Great to hear. I try to be pragmatic when it comes to dev.
@231kickback
@231kickback 3 жыл бұрын
Thanks for the video! I appreciated that the information was straight to the point.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@longuinni
@longuinni 3 жыл бұрын
Holy moly.... that was WOW. Very very helpfull. Please make more videos like this one...
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much Fernando! I'll try my best 😀
@NickBullCSharp
@NickBullCSharp 3 жыл бұрын
Wow this is fantastic. I didn't know about that this was occurring. Thanks Brian 👍
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you for watching
@Zonawanialonnua
@Zonawanialonnua 3 жыл бұрын
Incredible, it turns out it was easy! Thank you, Brian!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you for watching
@paulstanley2789
@paulstanley2789 3 жыл бұрын
Thanks for the awesome tutorial Brian really useful!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you for watching
@kopilkaiser8991
@kopilkaiser8991 Жыл бұрын
I really learnt a lot from this video. Not just the main topic which was discussed but how to give callbacks and using Actions to code formative and constructive code. Thank you bro. I am always following your coding practics as they are well formulated. Your explanation is easy to understand as well.
@BrianLagunas
@BrianLagunas Жыл бұрын
Thank you very much. I appreciate you.
@sneeznoodle
@sneeznoodle 3 жыл бұрын
Really helpful, even though my problem wasn't the exact thing described in this video, it still _really_ helped me fix it. Great video!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
So happy to hear that. Thanks for watching
@niranjannt637
@niranjannt637 Жыл бұрын
Really awesome way to handle async void !!! Thanks.
@kleberbueno.1978
@kleberbueno.1978 Жыл бұрын
Really great amazing tutorials. Keep doing that.
@BrianLagunas
@BrianLagunas Жыл бұрын
Thank you
@expertreviews1112
@expertreviews1112 Жыл бұрын
fantastic video! like your content on multitasking/async programming is incredible!
@BrianLagunas
@BrianLagunas Жыл бұрын
Thank you for watching
@AvnishKumar7
@AvnishKumar7 3 жыл бұрын
Wow, As a UWP Developer, it helps me a lot. Thanks, Brian
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you for watching. I'm glad this video was helpful.
@DevMicha
@DevMicha 3 жыл бұрын
Great and very useful video. Thank you very much!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Glad you enjoyed it!
@pramod722
@pramod722 2 жыл бұрын
Thanks Brian for the solution👍
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
@chrismantonuk
@chrismantonuk 3 жыл бұрын
Thanks Brian! Nice content and really like your presentation style. Quick question: would there be an issue awaiting the Task inside a void extension method? (Which then also has to be async). Thanks!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
As long as you pass your callbacks down the extension method stack it should be just fine. Thanks for watching.
@chrismantonuk
@chrismantonuk 3 жыл бұрын
Brian Lagunas thanks for the reply. I’ve always wrestled with how to await tasks in a constructor, so this is something I will start implementing straight away. Cheers!
@charlinagramonte3471
@charlinagramonte3471 3 жыл бұрын
Love it. Really nice video Brian!!!!! :)
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much!
@Kerbargos
@Kerbargos 3 жыл бұрын
Hey Brain I think you can be a king :) Thank you very much. I think this a life saver for a task implementetion. Very good job.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you very much for the kind words
@danzk
@danzk 3 жыл бұрын
Very helpful, thanks for the video!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
You're welcome 😁
@nandkishorsonwale69
@nandkishorsonwale69 3 жыл бұрын
Great Solution. Thank you.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@emiliowildberger7151
@emiliowildberger7151 3 жыл бұрын
Thank you very much Brian, I have learned a lot from you
@BrianLagunas
@BrianLagunas 3 жыл бұрын
I'm really happy I could help
@ievheniiierokhin1677
@ievheniiierokhin1677 3 жыл бұрын
Nice tips for Tasks...great job!!!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@Mareinsula
@Mareinsula 3 жыл бұрын
Reading your code feels like perfection. Thank you! With that now I think I can extend for many properties that require async to be filled.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much.
@arielspalter7425
@arielspalter7425 3 жыл бұрын
Fantastic tutorial. Subscribed!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for the sub!
@learner8084
@learner8084 Жыл бұрын
Great solution. Thanks.
@BrianLagunas
@BrianLagunas Жыл бұрын
Thanks for watching
@dotMorten
@dotMorten 3 жыл бұрын
Nice one! My simple rule of thumb: If you're forced to do async/void, you MUST have a try/catch block to deal with failures (which your extension in the end is essentially doing). Also not all .NET implementations silently fail but will bring down the entire application process if there's an unobserved task, so your first example of throw could bring down an entire app.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
That great to know. I haven't run into that yet personally, but I can see it definitely happening. Thanks for pointing that out.
@SharpGIS
@SharpGIS 3 жыл бұрын
@@BrianLagunas yeah I believe that's the behavior on .net native 😃. You can use the UnobservedTaskException global event to handle it though but again that's a last resort instead of your more elegant solution.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Did you reply to your comment using a different account 🤣
@SharpGIS
@SharpGIS 3 жыл бұрын
@@BrianLagunas I got split personality disorder when it comes to Google accounts 😃
@AlmirVuk
@AlmirVuk 3 жыл бұрын
This is great! Thanks Brian!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank for watching Almir!
@Emis333
@Emis333 3 жыл бұрын
Very nice and useful. Congrats.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@Emis333
@Emis333 3 жыл бұрын
@@BrianLagunas BTW how would the extension method look like when, say i am expecting a result from an async method Task, and i need it in a non async method or constructor?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@Emis333 Like this github.com/PrismLibrary/Prism/blob/master/src/Prism.Core/Extensions/TaskExtensions%7BT%7D.cs
@Emis333
@Emis333 3 жыл бұрын
@@BrianLagunas Amazing thanks :)
@matiascatanzariti1195
@matiascatanzariti1195 3 жыл бұрын
Great video found by chance for a problem I'm having. But don't want to miss this opportunity to tell you that your content in general is great. Your courses at pluralsight are great. But most important: I am really in love with Prism.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much. I greatly appreciate you and your kind words.
@krzysztofstepnikowski4150
@krzysztofstepnikowski4150 3 жыл бұрын
Perfect! This can help me! Awesome! Thanks :)
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Glad to hear it!
@sergiotardo
@sergiotardo 3 жыл бұрын
That's great!!!! I was looking for some solution to this situation,... a contructor that call a service to get data or anything that need to be done in an async way thanks a lot!!!!! excelent video as always!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Glad it helped. Thanks for watching
@CRBarchager
@CRBarchager Ай бұрын
Great explaination. I try to avoid async void when ever possible. The only place I've seen it used have been in developement with Winforms but nonetheless a good solution to the problem.
@sergiigolembiovskyi1365
@sergiigolembiovskyi1365 Жыл бұрын
Awesome one!
@BrianLagunas
@BrianLagunas Жыл бұрын
Thank you so much
@eltrukof
@eltrukof 2 жыл бұрын
thanks for the explanation
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
@md.khairulalam197
@md.khairulalam197 2 жыл бұрын
Really useful...Thanks...
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
2 жыл бұрын
Thanks dude! awesome.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
@thomasbarratt5333
@thomasbarratt5333 11 ай бұрын
Great solution! This helped me avoid having to bring in numerous additional dependencies into a very large legacy solution. I've expanded onto your extension method for Task public async static void Await(this Task task, Action completedCallBack, Action errorCallBack) { try { T result = await task; completedCallBack?.Invoke(result); } catch (Exception ex) { errorCallBack?.Invoke(ex); } }
@BrianLagunas
@BrianLagunas 10 ай бұрын
Nice! Thanks for sharing
@julianturner6203
@julianturner6203 3 жыл бұрын
Yes, do more please. Thanks Brian
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Will do! Thanks for watching.
@julianturner6203
@julianturner6203 3 жыл бұрын
@@BrianLagunas thanks man, you are awesome.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
You're too kind
@tomnolane
@tomnolane 2 жыл бұрын
very very very thanks, it's usefull
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
@osman3404
@osman3404 3 жыл бұрын
OMG! how am I just finding out about this simple technique :) By the way Brian, was there ever an explanation from MS as to why constructors are not allowed to have an await? I get. the feeling that it must be a good reason from application design prospective. For example I like the ViewModel constructors synchronously setup the default values for all the properties, wire the command handlers then give the View do its bindings. And once the UI is in valid loaded state, await in constructor limitation to enforce a coding practice.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Using await in a constructor would mean that the constructor would have to return a Task that represents a value that will be constructed in the future, instead of immediately returning the constructed value. This may cause a number of issues, if not a ton of confusion. That's just a guess though.
@MrSmsajin
@MrSmsajin Жыл бұрын
Superb Video! Appriciated! how can we await a Task in an object constructor which is returning the result?
@BurkusCat
@BurkusCat 3 жыл бұрын
I think I watched a livestream of you adding similar extension methods to Prism a while ago? Are those available to use yet?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Those are available in the latest nightly builds of Prism v8.
@stefan-d.grigorescu
@stefan-d.grigorescu Жыл бұрын
Awesome stuff, thank you for this idea! I wonder why isn't this extension already part of the microsoft libraries since these situations with the constructor seem to happen from time to time. Or why isn't there some logic to enforce an async constructor behavior?
@BrianLagunas
@BrianLagunas Жыл бұрын
Microsoft isn’t too opinionated about how things should be done. That’s probably a good thing.
@semen083
@semen083 3 жыл бұрын
The good solution for me to await task specifically in Viemodel constructor it is make a async command, add trigger for "Loaded" event of View and invoke this.
@markerickson9169
@markerickson9169 3 жыл бұрын
Awesomely simple!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you very much
@beautifulheartsoothingreci28
@beautifulheartsoothingreci28 3 жыл бұрын
Let's say you want to navigate to a page and on navigation to it you want to fetch data from the database and display in a list on that page. However I do not want the UI to be blocked while the data is being retrieved and I just wanna display an ActivityIndicator for that duration. Should I call "FetchDataFromDb().Await(...)" in the constructor of that page?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Usually, when navigating in an application, there is some type of built in navigation life-cycle that you can use to load your data.For example, in Prism I know when a view is beging navigated to or away from. I can use methods such as OnNavigatedTo to execute that code. However, if you do not have hooks like that, then yes. You can use this method to fire off an async method to fetch your data, and when that operation is completed you can hide your busy indicator.
@_samirdahal
@_samirdahal 3 жыл бұрын
Very good video 👍. Actually I was searching about the same topic. Thank you for sharing. But I have one more question. In real world project, is it a good practice to actually call a task method in a constructor? I mean the constructor is doing a lot of things then. The below code will only execute after awaiting the task? So other fields will initialize late. 🤔. Please can you explain this to me?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
There are usually better places to call async methods when creating an object. However, sometimes you need to do something in a ctor. No, the task is async and will not block the other fields from being initialized. The ctor will run exactly the same as if you didn't call an async method. Try it for yourself and you will see
@kasozivincent107
@kasozivincent107 3 жыл бұрын
Hello Brian. Thanks for this masterpiece. I remember telling you my views were lagging behind coz I was querying my dB from the constructor, this is going to save my day. In addition, could you one day make a video about The Infragistics Word and Excel engines plus the XamSpreadsheet control? I find the docs not really helpful. At least your videos make everything seem stupid easy. Thanks
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Sure thing. I do plan on doing videos on Infragistics products very soon. This is a popular request from our customers.
@kasozivincent107
@kasozivincent107 3 жыл бұрын
Thank you. Trust me this will save lives. As you always say “one can’t miss what they don’t know” I have infragistics on this machine, I can smell the amount it can fetch me if I built apps using it. But it’s not easy to use. I am waiting for those videos as you waited for your new machine😹😹.
@muhammadwaqasaziz4054
@muhammadwaqasaziz4054 3 жыл бұрын
You are awesome MAN!!!!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much!
@thomasberthelsen9581
@thomasberthelsen9581 3 жыл бұрын
Our application has crashed... This is good! haha, that was nice way to put it :D
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@99MrX99
@99MrX99 3 жыл бұрын
So you would suggest for events not making them async void, but normally void and in there calling an async method like shown in your video?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Yes, that is the purpose of this extension method. Anywhere you are forced to have an async void method that awaits a task, use this extension method instead. The most common places that will happen is in event handlers and commands
@HrishiGhadekar
@HrishiGhadekar 3 жыл бұрын
That was awesome. I learn MVM with prism from your videos. Can you have or create a tutorial on MVVM on dotnet core?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Sure can, but it won't be any different than an MVVM video for .NET Framework. It's literally the same. Is there something specific you are having troubles with?
@makimupan4ur
@makimupan4ur Жыл бұрын
I leave the super LIKE! It must sound as MONSTER KILL like in UT! SUPER LIKE!
@BrianLagunas
@BrianLagunas Жыл бұрын
Thank you so much
@michaelalbaladejo6017
@michaelalbaladejo6017 3 жыл бұрын
Thank you for this very interesting video. You say one of the async void problems is testability. I don't see how this method improves testability. How can the unit test wait for the Task?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
It improves testability because your methods no longer have to be async void. They can be of type Task, and unit tests can easily test a Task method. async void methods cannot be tested a you cannot await the result.
@munawarkhurshid1201
@munawarkhurshid1201 3 жыл бұрын
Brian can you suggest a work around for Delegate Command. How can I await execute Action in the delegate command. Here is a Delegate Command created in the VM constructor this.RefreshTimeCommand = new DelegateCommand(loadTime, canLoadTime).ObservesProperty(() => canRefresh);
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Yeah, check out this video kzbin.info/www/bejne/hWK3qWChabuUpZI
@fmonteiropt
@fmonteiropt 2 жыл бұрын
Code alien 👾, amazing !!
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thank you for watching
@SlowAside5
@SlowAside5 3 жыл бұрын
Hi Brian. I have a tech question. Is it possible to implement an async ICommand? To my knowledge, this interface does not support async, but I've seen some discussion online on attempts to work around this. It is somewhat of a confusing topic and I would be interested to get your take on this. Thanks.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Technically no. There is no such thing as an async command, because the framework only provides ICommand an its methods are invoked synchronously. Now, those "async commands" are just faking it to try and eliminate that scary async void method definitions. An AsyncCommand basically just lets you await a task method with some possible additional features like knowing if it's running, maybe cancel it, and maybe respond to completion or errors. There are other ways to handle Task methods for a command that doesn't involve creating a new command type.
@SlowAside5
@SlowAside5 3 жыл бұрын
@@BrianLagunas Thanks for your response. What other ways are you referring to?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@SlowAside5 you could use the async in the delegate declaration, you could just do async void, you could use the extension method I showed in my video about async void just to name a few.
@SlowAside5
@SlowAside5 3 жыл бұрын
Brian Lagunas I see, thanks. I think my confusion was over to how to execute an ICommand in a unit test when it had an async action in it. I ended up putting that action in its own method and then testing that method directly. I guess I will be skeptical about the need for AsyncCommand going forward.
@charmerpppify
@charmerpppify 3 жыл бұрын
Awesome!!!
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@andreikashin
@andreikashin 3 жыл бұрын
Thanks, Brian. Now the next question - how to work with ConfigureAwait()?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Watch this video kzbin.info/www/bejne/fGrCaYCAl9ihsMk
@merwintf
@merwintf 3 жыл бұрын
Hey Brain! I was wondering if you have any github implementation, I was following up with your blog and you did mention the production code will be different! I just wanted to have a look at how things were implemented, if yes can you share the link to github repo may be? Great content btw Thanks.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Sorry, I didn't put this on github. I should probably start doing that. Thanks for the tip
@merwintf
@merwintf 3 жыл бұрын
@@BrianLagunas Thank you and its very useful content , please let us know if you do though :)
@InterRubke
@InterRubke 3 жыл бұрын
Could you do a vid about TaskValue and when is it appropriate to use?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Ohh.. that would be a good one.
@JeremySinclair
@JeremySinclair 3 жыл бұрын
Whoa! So.... This was something very useful and I have places to use this already 🤔🤔
@BrianLagunas
@BrianLagunas 3 жыл бұрын
That's great to hear Jeremy! Thanks for watching
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Also, I didn't show it in the video, but keep in mind that you can actually return the Task result in your callbacks :)
@dracomalfoy1245
@dracomalfoy1245 7 ай бұрын
very well explained, however I think it could have been made a little simpler by not using extension methods and Actions , since they are both off topic. Other than that great video!!. Thank you!!.
@algorithman2129
@algorithman2129 3 жыл бұрын
Hi @Brian Lagunas (and everyone): I found some nearly identical TaskExtensions in System.Threading.Tasks. I do not know where they're coming from, my best guess is netstandard. The thing is, they have exactly your wording, but they are missing the async (e.g. public static void Await(this Task task, Action completedCallback, Action errorCallback) ). And they do NOT work as yours do. Brian, you have way more insight where this might come from, can you please tell them to fix it or to lose them altogether, because atm they do not wait. (Working on a netCore3.1 app and bringing my dialogs to life now)
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Hmmmm.... sorry, but I do not know anything about those extension methods. Are you sure those are in the framework and not in your project somewhere, or possible in a dependency you have? Put your cursor on the method and press F12. That will take you to the definition. You'll find out real quick where it lives. Don't look at the namespace, look at the assembly it is defined in.
@algorithman2129
@algorithman2129 3 жыл бұрын
​@@BrianLagunas I was completely off, sorry. They come from Prism 8.0.0.1740. Edit: Resharper did decompile it but without any clue which assembly its from.
@algorithman2129
@algorithman2129 3 жыл бұрын
Don't bother Brian, my mistake. I had a slight misunderstanding. Sorry again.
@hanspetervollhorst1
@hanspetervollhorst1 3 жыл бұрын
But the extension method itself is still not awaited, or is it? If we had an instruction in the constructor after DoSomething().Await() then it would still be called immediately and not after DoSomething() completed? I don't really understand why the exception inside the Await() Method leads to the application crushing while an exception inside DoSomething() is being ignored
@hanspetervollhorst1
@hanspetervollhorst1 3 жыл бұрын
DoSomething().RunSynchronously() appears to be a safer approach here, no?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Yes, the extension method awaits the Task. Correct, the invocation f code will continue after the DoSomething().Await() method call. However, you use the completed callback of the extension method to invoke any code you want in response to the completion of the task. Tasks exceptions are thrown within the context of the task. This is why async void is so bad as the exceptions are not handled properly.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@hanspetervollhorst1 You do not want to try and force async code to run synchronously.
@Unison_007
@Unison_007 2 жыл бұрын
спасибо)
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thanks for watching
@MrTellus
@MrTellus 3 жыл бұрын
Weird example. There is no async void in your code example but the one you created (the extension method). What about Task.Run(async () => await DoSomething()); in ctor instead?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Maybe I didn't do a great job of explaining it. The point is to avoid async void methods. Usually when trying to use a task in a ctor, many make the task an async void method. This is bad. Instead, keep the method a task and still properly await the task, handle the completion, and handle any errors. I could have been more clear there. You sample would not accomplish the goal as you would still need to await the Task.Run which you can't do in the ctor. Not to mention that code is highly inefficient.
@CezarWagenheimer
@CezarWagenheimer 3 жыл бұрын
Will It block the UI or will run in a separate thread?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
It will not block the UI. If you were to take my sample and set the Text property to a value in the ctor after our DoSomething().Await() call, you will see that the ctor continues to run as expected while the task runs.
@DoctorMGL
@DoctorMGL 2 жыл бұрын
Genius Dayuuuuum son wp
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thank you for watching
@n.sharma5810
@n.sharma5810 Жыл бұрын
Hi Brian, if possible please create a series on wpf mvvm for beginners
@BrianLagunas
@BrianLagunas Жыл бұрын
What does that series look like to you?
@beautifulheartsoothingreci28
@beautifulheartsoothingreci28 3 жыл бұрын
But how is this possible? Why can't you just await a Task in a constructor, yet with the extension method you can?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
It's magic 😂
@renatojr2010
@renatojr2010 3 жыл бұрын
Excellent, I had a doubt and if I want to get the result of the Task how would I do it?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Then instead of Action, it would be Action completedCallBack. Then pass the value from the task to the callback. completedCallback?.Invoke(value);
@renatojr2010
@renatojr2010 3 жыл бұрын
@@BrianLagunas Hi, I implemented following your idea but it is no longer an extension method, could you give me an example?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@renatojr2010 I don't understand. How is it not an extension method if you followed my code?
@renatojr2010
@renatojr2010 3 жыл бұрын
@@BrianLagunas I was able to use Action as directed. Thank you.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@renatojr2010 I'm glad you figured it out
@shavais33
@shavais33 2 жыл бұрын
I like the Completed, HandleError callback pattern, but if you await from your main thread, it will block, causing your entire app to be unresponsive for 3 seconds. That kind of defeats the purpose of doing something in a background thread. I'd like to see a good way to run async tasks from the main thread without blocking the main thread.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
If the method you are awaiting is async, then it will not block your main thread.
@shavais33
@shavais33 2 жыл бұрын
@@BrianLagunas But you can't call an async from a non-async.. Oh I see what you're doing, you're calling your Await extension without await-ing it. Ok that's brilliant. You just earned yourself another subscriber.
@peepeefrog_
@peepeefrog_ 3 жыл бұрын
nice
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@pranabkumarde5634
@pranabkumarde5634 2 жыл бұрын
hi Brian, your content was really helpful. Though I have one doubt. Below is one code which is returning "Data processing incomplete." when I call 'ProcessData'. If I am missing anything ? I appreciate your help. Thanks ! class LongJob { bool _dataLoaded = false; public LongJob() { LoadDataAsync().Await(); } public void ProcessData() { if (_dataLoaded) { Console.WriteLine("Data processing completed."); } else { Console.WriteLine("Data processing incomplete."); } } public async Task LoadDataAsync() { await Task.Delay(3000); _dataLoaded = true; } } static class TaskExtensions { public async static void Await(this Task t) { await t; } }
@BrianLagunas
@BrianLagunas 2 жыл бұрын
You didn't provide a callback in your Await method, so unless you wait over 3 seconds before calling your Process Data, the async call isn't complete yet.
@MrBan001
@MrBan001 3 жыл бұрын
Why is this Extension not part of the Framework? There must be a reason?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Good question. Maybe they have plans to natively support fire and forget tasks in the ctor in a future release of C# 😁
@MrBan001
@MrBan001 3 жыл бұрын
@@BrianLagunas IHost for example blocks the thread completele until shutdown after they call Run()
@MrBan001
@MrBan001 3 жыл бұрын
Mh thats not async ...
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@MrBan001 I'm not sure I understand what you are trying to say, but this extension allows your async code to run on it's worker thread, while the rest of your sync code executes on the UI thread. You can also control which thread the CompletedCallback runs on by using COnfigureAwait in the extension.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@MrBan001 Are you talking about calling BuildWebHost(args).RunAsync() in the Main method in an ASP.NET Core app? If so, that's a completely different animal.
@danyelaristizabal
@danyelaristizabal 3 жыл бұрын
Genius
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you very much
@shavais33
@shavais33 2 жыл бұрын
I liked this video, but I wonder if is it effective to ask for subscriptions and likes at the very beginning of a video? I feel like that's sort of like asking for the sale before you've presented the product. I suppose if most of the people watching are existing followers, they're anticipating appreciating the content and just need reminding. I don't know, just a thought.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Think of it like buying a movie ticket before you see the movie. Or buying a theme park ride ticket before you go on the ride. Except in this case, it actually doesn't cost anything at all 😁
@shavais33
@shavais33 2 жыл бұрын
@@BrianLagunas So.. because the like button influences the KZbin algorithm and thereby influences how many viewers you get which influences how much money you make, and since many people forget to press the like button if they wait until the end to press it even if they did like it, you want people to lie, or.. take it on faith they they will like the video, let's say.. and indicate that they like a video they haven't even seen yet. The like button IS NOT a ticket to watch. That's NOT its intent. Its intent is to act as an indication that the person pressing it liked the video. That's its intent. To me, content creators who are pushing this idea that it's a "ticket to watch" come off as greedy, pushy business people willing to bend the truth and maybe even be kinda just a bit bully-ish for the sake of their bottom line. I realize that trying to get financial traction as a YT content creator is a tough row to hoe, and I don't envy that position, and I appreciate the effort, but I think pressuring people to like and subscribe before they've even watched a video is going too far. It puts me in mind of how we used to have free TV, paid for by commercials. Cable sold us all on the idea of paying for TV with no commercials, so we all started paying money per month for it. Then they went and put all the commercials back in even though we were sold the idea of cable based on there being no commercials! I'm still chaffed about that. I canceled my cable TV service when they did that and I've never looked back. So now we have streaming services that have no commercials, that's great, but to get decent content you have to pay for multiple streaming services, which is just ridiculous. Anyway. No, sorry sir, but it's not a ticket to watch, it's a like button, and I don't press one unless something in a video inspires me to. However, as it happens - I did like this video, and I like you, actually, despite our disagreement about this, and I did press the like button on this page. =)
@BrianLagunas
@BrianLagunas 2 жыл бұрын
@@shavais33 Actually, you make some valid points. It's hard for creators to find a balance between playing by KZbin rules and not coming off like a pushy salesperson. I will try an experiment. I will no longer ask for likes on my next few videos. I will then compare the number of likes on those videos to my past videos and see if there is a noticeable drop in likes. I still might ask for subs though 😁. I'm glad you enjoy my content, and thanks for your feedback. I appreciate you taking the time to help me improve my channel. Let's see how this experiment goes.
@yevheniytymchishin8401
@yevheniytymchishin8401 3 жыл бұрын
It is possible to test "asyn void" methods via this library github.com/StephenCleary/AsyncEx Just do: AsyncContext.Run(() => ...your_async_void_action...); Assert.....
@guruprasadhmahalingam7715
@guruprasadhmahalingam7715 3 жыл бұрын
"Awesome"
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thanks for watching
@himanshugupta539_
@himanshugupta539_ 3 жыл бұрын
I was using await task.Run() And calling my async task in that Also for errors Used .ContinueWith() And check if t.IsFaulted
@BrianLagunas
@BrianLagunas 3 жыл бұрын
That can be problematic and very inefficient. Stephen Cleary has a great post series on Task.Run that explains this in detail.
@mottahh4162
@mottahh4162 3 жыл бұрын
isn't this similar to GetAwaiter().GetResult()?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
No, the GetResult will force your code to act synchronously and wait for the execution of the method call. Using my approach, your code will still fire async, but notify you when the task has completed. Plus, I would argue that you're not meant to use GetResult(). It's meant to be for compiler use only, not for you.
@mottahh4162
@mottahh4162 3 жыл бұрын
@@BrianLagunas Thank you
@mauricibarth9503
@mauricibarth9503 2 жыл бұрын
Why your videos haven't subtitles?
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Because I can’t afford them 😁
@mauricibarth9503
@mauricibarth9503 2 жыл бұрын
@@BrianLagunas I didn't know this is paid. I from Brazil, and it help me. Thanks for answer me.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
Thank you for supporting my channel
@AngusMcIntyre
@AngusMcIntyre 3 жыл бұрын
People _need_ to stop saying that async void exceptions kill your process. They do not. They kill the work item on the thread. Your application keeps running.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
That's what they mean when they say that.
@eeevans
@eeevans 3 жыл бұрын
Great technique but not really async void. This was async Task called from non async method. What about async void called by the framework.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Async void is when you would use this method. The framework does not call async void methods specifically. For example, a button click event handler. You would not make that async void because that's bad. Instead, you would use this technique to call the task async, but also be notified when the result has been returned. This allows you to keep your methods a Task and use them within other void methods that would otherwise be "async void". I probably could have done a better job of clarifying that point.
@andreikashin
@andreikashin 3 жыл бұрын
That is digital magic
@BrianLagunas
@BrianLagunas 3 жыл бұрын
Thank you so much
@Stickman550
@Stickman550 2 жыл бұрын
5:10 I never thought an application crashing could be a good thing lol
@BrianLagunas
@BrianLagunas 2 жыл бұрын
If something fails, you need to know about it
@tcl78
@tcl78 2 жыл бұрын
It is not clear to me why you couldn't just await the method in the constructor and why you had to introduce an extension to do that. Isn't it pretty much equivalent than awaiting the method in the constructor? I mean, isn't the extension method async too? Why don't you need to await it just the same as the original method? Also, the whole point of async/await was too get away from the callback hell, here you are reintroducing callbacks to make async work inside a constructor...
@BrianLagunas
@BrianLagunas 2 жыл бұрын
As I explained in the video, you can't await a method in a constructor. This is a work-around for when you need to handle the completion of an async method in a ctor. You need the callback.
@paulp4061
@paulp4061 2 жыл бұрын
You are still firing and forgetting your .Await() method from the constructor. If DoSomething() is part of the object initialization code then why does it keep running for another 3 seconds after constructor has exited? If an exception occurs in the initialization code it should cause constructor to crash but instead it lets the object to be created successfully and you can use it for the whole 3 seconds before it tells you (if you ask) that something went wrong. And it is still not testable.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
No. This is not fire and forget. Fire and forget is when you invoke the async method and there is no response. The method does its work and you have no idea about its results or of it ever completed. You can continue to use this object regardless of if an an exception occurred or not because the creation of the object is not stopped. The scenario you are using implies that this code is required for the object initialization. This may not always be the case. In those instances, this approach will help.
@paulp4061
@paulp4061 2 жыл бұрын
@@BrianLagunas If it’s not required for the initialization then why is it being called from the constructor? And therefore, if DoSomething() fails then the constructor should fail, which it doesn’t. I faced this exact issues twice recently and in one case I ended up separating the slow initialization part into InitAsync() method which needs to be called manually after instantiating the object and then every other method that depends on it needs to check “if (_hasBeenInit)”, which is super ugly. In the other case I am calling Init synchronously from the constructor: InitAsync()/GetAwaiter.GetResult() which is also wrong for obvious reasons but at least it allows me to inject my class and be certain that it had been fully initialized. I wish there were a nicer way of doing it.
@BrianLagunas
@BrianLagunas 2 жыл бұрын
@Paul P There are many scenarios in which you want to run code that is not required for the object creation. Things such as analytics, messaging, loading initial data that may not be required for the class to function. While your specific scenario may not be a good use of this approach, there are many others than can benefit. Your scenario sounds like it would be better to have a factory asynchronously create your object instead. This way you can await the creation of the object.
@jakubsuchybio
@jakubsuchybio 3 жыл бұрын
Nice short video, I like it. Buuuuuut Am I missing something? You are talking about problem with "async void", but from the start you are using "async Task DoSomething()"... What you are fixing is completely different problem than async void, isn't it? You are fixing fire&forget task. If someone would implement it like this. It's their job to handle errors inside DoSomething, when it is called as fire&forget (e.g. without await). If you want to never get into this problem, you can simply use "TaskScheduler.UnobservedTaskException" event and catch all these fire&forget exceptions there. Getting back to "async void" problem. If I recall correctly, the main issue with it is, that the exception thrown from that is not even catched with "TaskScheduler.UnobservedTaskException" event. Because without a Task, you can't save a call stack to that Task to be unobserved. So basically the only solution to "async void" is to try/catch the entire "async void" inside to get ever any handling of errors inside "async void" Am I wrong?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
I could have explained this better in the video, but when calling code in the ctor of an object, the common approach people take is to make the method async/void, but then they introduce all the problems I mentioned. Using the extension method, you can keep your method a Task and still call it within the ctor of an object, while handling the completion, the result, and any exceptions that may occur. Also, async void is often referred to as "fire and forget" but this isn't accurate. Async void methods can still block the caller if execution doesn't run into an await statement, and even then, it can still block the caller if the await call runs synchronously.
@2006lilmoe
@2006lilmoe 3 жыл бұрын
GetAwaiter().GetResult() ?
@BrianLagunas
@BrianLagunas 3 жыл бұрын
No, the GetResult will force your code to act synchronously and wait for the execution of the method call. Using my approach, your code will still fire async, but notify you when the task has completed. Plus, I would argue that you're not meant to use GetResult(). It's meant to be for compiler use only, not for you.
@2006lilmoe
@2006lilmoe 3 жыл бұрын
@@BrianLagunas it's for unwrapping the aggregate exception, which you'd want. If you're just "testing" then there's no issue in blocking. Event handlers should only be forwarding the events to proper async methods in which are tested separately. That's not duplication. Anyway, these workarounds are all unnecessary hacks that augment the flawed async implementation in .net framework. Should be fixed in core.
@BrianLagunas
@BrianLagunas 3 жыл бұрын
@@2006lilmoe I agree this is an issue with it's implementation. Sometimes I wish this was never invented. I didn't have a problem doing the old way of async programming before this 😂
@auronedgevicks7739
@auronedgevicks7739 3 ай бұрын
yeah .. no. This video is so wrong. "why async void" is bad (He is still using async void). "How do I await task in Ctor" (He is still not awaiting the task).
@soho1080
@soho1080 Жыл бұрын
Worthwhile to ask if this only applicable to UI apps as the behavior isn't the same in Console apps.
@BrianLagunas
@BrianLagunas Жыл бұрын
Yes
Append the WPF Window ContextMenu using Interop
9:45
Brian Lagunas
Рет қаралды 1,6 М.
Which do I use, ConfigureAwait True or False?
6:53
Brian Lagunas
Рет қаралды 35 М.
Эффект Карбонаро и бесконечное пиво
01:00
История одного вокалиста
Рет қаралды 6 МЛН
TRY NOT TO LAUGH 😂
00:56
Feinxy
Рет қаралды 10 МЛН
🍟Best French Fries Homemade #cooking #shorts
00:42
BANKII
Рет қаралды 57 МЛН
C# Yield Return: What is it and how does it work?
15:09
Brian Lagunas
Рет қаралды 54 М.
8 await async mistakes that you SHOULD avoid in .NET
21:13
Nick Chapsas
Рет қаралды 308 М.
C# Async Yield Return: IAsyncEnumerable will change your life!!!
10:13
Avoiding Async Void
16:49
Coding Tutorials
Рет қаралды 2,2 М.
C# Async Await Mistakes | Part 1
10:19
Amichai Mantinband
Рет қаралды 30 М.
Task vs ValueTask: When Should I use ValueTask?
10:43
Brian Lagunas
Рет қаралды 19 М.
IAsyncEnumerable, My Favorite C# 8 Feature That No One Is Using
11:02
Amichai Mantinband
Рет қаралды 23 М.
Stop using async void in C#! Do this instead.
13:12
Nick Chapsas
Рет қаралды 57 М.
Cadiz smart lock official account unlocks the aesthetics of returning home
0:30
Will the battery emit smoke if it rotates rapidly?
0:11
Meaningful Cartoons 183
Рет қаралды 9 МЛН