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!
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.
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.
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 :)
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 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.
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.
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); } }
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.
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?
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.
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.
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!
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!
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 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?
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?
Good video. I don't get one moment. How did background thread from thread pool changed text on UI? Method DoSomething is executed fully on background thread?
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);
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
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😹😹.
@@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.
@@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.
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?
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.
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.
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?
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
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
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.
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 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.
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
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)
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.
@@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.
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.
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 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.
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.
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?
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.
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!!.
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.
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?
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.
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.
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.
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; } }
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.
It is possible to test "asyn void" methods via this library github.com/StephenCleary/AsyncEx Just do: AsyncContext.Run(() => ...your_async_void_action...); Assert.....
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.
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 😁
@@BrianLagunas So.. because the like button influences the UA-cam 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. =)
@@shavais33 Actually, you make some valid points. It's hard for creators to find a balance between playing by UA-cam 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.
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.
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.
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.
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.
@@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.
@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.
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...
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.
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?
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.
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.
@@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.
@@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 😂
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).
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!
Thank you so much for the kind words. It motivates me to create more content.
short and to the point & solves problems with quick useful examples instead of long lectures -- channel is very underrated!
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.
Thank you so much for the kind words. My goal is to always keep my tutorials to under 15 minutes max.
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.
Great to hear. I try to be pragmatic when it comes to dev.
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 :)
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? 😁
@@BrianLagunas Deal 😃😃
I will surely share with people I know in software field
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.
That great to know. I haven't run into that yet personally, but I can see it definitely happening. Thanks for pointing that out.
@@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.
Did you reply to your comment using a different account 🤣
@@BrianLagunas I got split personality disorder when it comes to Google accounts 😃
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.
Thank you very much. I appreciate you.
Holy moly.... that was WOW. Very very helpfull. Please make more videos like this one...
Thank you so much Fernando! I'll try my best 😀
Wow, As a UWP Developer, it helps me a lot. Thanks, Brian
Thank you for watching. I'm glad this video was helpful.
fantastic video! like your content on multitasking/async programming is incredible!
Thank you for watching
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);
}
}
Nice! Thanks for sharing
Really awesome way to handle async void !!! Thanks.
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.
Thank you so much. I greatly appreciate you and your kind words.
Really helpful, even though my problem wasn't the exact thing described in this video, it still _really_ helped me fix it. Great video!
So happy to hear that. Thanks for watching
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?
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.
Thanks for the video! I appreciated that the information was straight to the point.
Thanks for watching
Really great amazing tutorials. Keep doing that.
Thank you
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.
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.
Thank you so much.
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!
As long as you pass your callbacks down the extension method stack it should be just fine. Thanks for watching.
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!
Thanks Brian for the solution👍
Thanks for watching
Great Solution. Thank you.
Thanks for watching
Wow this is fantastic. I didn't know about that this was occurring. Thanks Brian 👍
Thank you for watching
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!
Glad it helped. Thanks for watching
Very helpful, thanks for the video!
You're welcome 😁
Great and very useful video.
Thank you very much!
Glad you enjoyed it!
Incredible, it turns out it was easy!
Thank you, Brian!
Thank you for watching
Very nice and useful. Congrats.
Thanks for watching
@@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?
@@Emis333 Like this github.com/PrismLibrary/Prism/blob/master/src/Prism.Core/Extensions/TaskExtensions%7BT%7D.cs
@@BrianLagunas Amazing thanks :)
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?
Microsoft isn’t too opinionated about how things should be done. That’s probably a good thing.
Good video. I don't get one moment. How did background thread from thread pool changed text on UI? Method DoSomething is executed fully on background thread?
Nice tips for Tasks...great job!!!
Thanks for watching
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.
Thank you very much for the kind words
Superb Video! Appriciated! how can we await a Task in an object constructor which is returning the result?
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);
Yeah, check out this video ua-cam.com/video/O1Tx-k4Vao0/v-deo.html
Yes, do more please. Thanks Brian
Will do! Thanks for watching.
@@BrianLagunas thanks man, you are awesome.
You're too kind
Thanks for the awesome tutorial Brian really useful!
Thank you for watching
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
Sure thing. I do plan on doing videos on Infragistics products very soon. This is a popular request from our customers.
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😹😹.
Fantastic tutorial. Subscribed!
Thanks for the sub!
Thank you very much Brian, I have learned a lot from you
I'm really happy I could help
Why is this Extension not part of the Framework? There must be a reason?
Good question. Maybe they have plans to natively support fire and forget tasks in the ctor in a future release of C# 😁
@@BrianLagunas IHost for example blocks the thread completele until shutdown after they call Run()
Mh thats not async ...
@@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.
@@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.
That was awesome. I learn MVM with prism from your videos. Can you have or create a tutorial on MVVM on dotnet core?
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?
Our application has crashed... This is good! haha, that was nice way to put it :D
Thanks for watching
Could you do a vid about TaskValue and when is it appropriate to use?
Ohh.. that would be a good one.
Love it. Really nice video Brian!!!!! :)
Thank you so much!
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.
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.
thanks for the explanation
Thanks for watching
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?
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
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
DoSomething().RunSynchronously() appears to be a safer approach here, no?
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.
@@hanspetervollhorst1 You do not want to try and force async code to run synchronously.
Perfect! This can help me! Awesome! Thanks :)
Glad to hear it!
very very very thanks, it's usefull
Thanks for watching
Hi Brian, if possible please create a series on wpf mvvm for beginners
What does that series look like to you?
Thanks dude! awesome.
Thanks for watching
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.
If the method you are awaiting is async, then it will not block your main thread.
@@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.
Awesome one!
Thank you so much
This is great! Thanks Brian!
Thank for watching Almir!
Really useful...Thanks...
Thanks for watching
But how is this possible? Why can't you just await a Task in a constructor, yet with the extension method you can?
It's magic 😂
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?
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
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)
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.
@@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.
Don't bother Brian, my mistake. I had a slight misunderstanding. Sorry again.
Excellent, I had a doubt and if I want to get the result of the Task how would I do it?
Then instead of Action, it would be Action completedCallBack. Then pass the value from the task to the callback. completedCallback?.Invoke(value);
@@BrianLagunas
Hi, I implemented following your idea but it is no longer an extension method, could you give me an example?
@@renatojr2010 I don't understand. How is it not an extension method if you followed my code?
@@BrianLagunas I was able to use Action as directed. Thank you.
@@renatojr2010 I'm glad you figured it out
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.
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.
@@BrianLagunas Thanks for your response. What other ways are you referring to?
@@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.
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.
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?
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.
Thanks, Brian. Now the next question - how to work with ConfigureAwait()?
Watch this video ua-cam.com/video/F9_8MJbsnzg/v-deo.html
I think I watched a livestream of you adding similar extension methods to Prism a while ago? Are those available to use yet?
Those are available in the latest nightly builds of Prism v8.
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!!.
Awesomely simple!
Thank you very much
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.
Sorry, I didn't put this on github. I should probably start doing that. Thanks for the tip
@@BrianLagunas Thank you and its very useful content , please let us know if you do though :)
Why your videos haven't subtitles?
Because I can’t afford them 😁
@@BrianLagunas I didn't know this is paid. I from Brazil, and it help me. Thanks for answer me.
Thank you for supporting my channel
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?
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.
I leave the super LIKE! It must sound as MONSTER KILL like in UT! SUPER LIKE!
Thank you so much
Will It block the UI or will run in a separate thread?
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.
isn't this similar to GetAwaiter().GetResult()?
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.
@@BrianLagunas Thank you
Whoa! So.... This was something very useful and I have places to use this already 🤔🤔
That's great to hear Jeremy! Thanks for watching
Also, I didn't show it in the video, but keep in mind that you can actually return the Task result in your callbacks :)
Code alien 👾, amazing !!
Thank you for watching
You are awesome MAN!!!!
Thank you so much!
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;
}
}
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.
I was using
await task.Run()
And calling my async task in that
Also for errors
Used .ContinueWith()
And check if t.IsFaulted
That can be problematic and very inefficient. Stephen Cleary has a great post series on Task.Run that explains this in detail.
спасибо)
Thanks for watching
It is possible to test "asyn void" methods via this library github.com/StephenCleary/AsyncEx
Just do:
AsyncContext.Run(() => ...your_async_void_action...);
Assert.....
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.
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 😁
@@BrianLagunas So.. because the like button influences the UA-cam 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. =)
@@shavais33 Actually, you make some valid points. It's hard for creators to find a balance between playing by UA-cam 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.
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.
That's what they mean when they say that.
Awesome!!!
Thanks for watching
Great technique but not really async void. This was async Task called from non async method. What about async void called by the framework.
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.
nice
Thanks for watching
5:10
I never thought an application crashing could be a good thing lol
If something fails, you need to know about it
That is digital magic
Thank you so much
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.
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.
@@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.
@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.
Genius Dayuuuuum son wp
Thank you for watching
"Awesome"
Thanks for watching
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...
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.
Genius
Thank you very much
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?
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.
GetAwaiter().GetResult() ?
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.
@@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.
@@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 😂
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).
Worthwhile to ask if this only applicable to UI apps as the behavior isn't the same in Console apps.
Yes
Great solution. Thanks.
Thanks for watching