C# Async / Await - Make your app more responsive and faster with asynchronous programming

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
have you ever tried to get into asynchronous programming already get stuck on all the complicated keywords or maybe you found out that while it sounded great he just couldn't get it to work in the real world well in this video I'm going to show you how to make use of a singers programming with very little effort my name is Tim quarry and my goal is to teach developers how learn c-sharp the easy way in this video that means I'm gonna be skipping all the history of threading that may enter some people but it really isn't relevant to what you need to know today instead what you need to know is how to use async and await in the real world to make your apps faster and more responsive now just to be clear about what we're talking about let's go over what I mean by a synchronous versus asynchronous synchronous programming is work that gets done in sequence task a gets done then task B then task C and finally task D the problem is that no one else can do any work until task D gets completed asynchronous programming allows us to fix that problem there are two big benefits here SC right away when you use it the first big benefit is in your user interface if task B takes a long time that will lock up your user interface by executing a task asynchronously while their way and complete control can be given back to the user interface so it's still responsive the second benefit comes into play especially when tasks C and D don't rely on task B in fact maybe none of the tasks depending each other may they're all just things that need to be done we don't need to get data back in that case we can execute them in parallel that means as long as your system has the resources it will try to do all four tasks at once if each task took three seconds to execute instead of taking a total of 12 seconds to complete it might only take four seconds hopefully you at least have an understanding now what we're talking about I think I'll get even clearer we look at the code before we do just a reminder it'd be great if you give this video a thumbs up and also just make sure you're subscribe to the channel okay so let's switch over to visual studio as you can see I already have a demo app set up I wind it put some basic code together that I needed to run the demo but that didn't really apply to we're talking about I'll give you a quick run three before get started so this is until UPF application I just has one form here for the user interface it has a couple of basic things on it it's got two buttons and it's got this results pane down here now you may have you'll see the results pane but that's right here it's called results window so we're going to do is we're on execute a task the way they normally would using this button and see the results down here and we'll see the user interface locks up and it takes a little while and a waste to display the information on screen and then we're going to do is where I use this button here the async execute to allow us to do the same task but asynchronously and we'll see how I can use the user interface still and how you can actually even see the answers come in one line at a time and set up all at once at the end like it doesn't normalize acute and we'll see all that in a little bit but that's our basic demo user interface now just a quick disclaimer here this is a DPF app and I'm not using mvvm I usually use mvvm with any kind of real WPF application but in this case it's just a demo the other thing to note is I really don't like the idea of putting code behind your user interface and the reason why is because when that code says back there it can't be used if you go to a different user interface you get I can't extract it and pull it and it just makes a mess and so I really recommend you don't put code in the code behind except for what is necessary to get data out of the screen and off the screen but in this case again since there's a demo I have put all my code in the code behind just can't break yourself don't do this for a real application it's just a demo okay so the code behind here I've got a few things already set up first I have to button click events the execute sync click which that's this one right here and then the execute async click which me that's one right there so the execute async is blank right now execute sync has some code in it and what this code does is as follows first we've got the stopwatch to start new and so I'm doing is I'm timing how long this takes so the way to do that is to start this stopwatch timer now you don't want to use a date/time dot now and try and grab that we there's not quite as precise this is much more precise or you start a stopwatch and then at the very end we stop it and so everything in between gets timed and we'll say okay here's the elapsed milliseconds between this line right here and this line right here which in theory will record how long this runs for so there is an even more precise way of doing things if you really want to get down you know deep into tracking your performance but this is a really good performance counter for you know general stuff so that's we're going to do we're just gonna have this stopwatch start it's built right into the dotnet framework so you don't need any special libraries for it you just run this line of code here it says start new then you run your code and usually stop and grab the elapsed milliseconds so that's all we're doing here and the last thing we do is we write out to the results window a line that says here's a total execution time for that action so in between there's this one action here called run download async I'm sorry run download sync so let's look at what it does we come down here run download sync says first give me the prep data which the prep data is just a list of string the a bunch of websites Yahoo Google Microsoft CNN Code project Stack Overflow so just a list a string that it gets back and it also clears out the results Windows Start so once it gets that prep data then it loops through each website and calls this download website and it passes in the website URL so the download website does is it just creates a new web client again built in net stuff and then it downloads a string that represents the entire index page now the reason I'm using this is because it's a great simulator of us asking for data and waiting for it to be done some websites are pretty responsive some not so much now the other hand note here is I'm actually building a website model I call it output where I put the website URL we loaded and then the actual data we got as well I returned that set of dia and there's that model right there website URL data pretty simple just two properties so the reason I do that is so I can keep the information together the actual website URL and then the actual data for the for this site now I don't actually use a data I just use the length of data to show me how big the website was in terms of characters okay so back up here we run the download sync so run download sync downloads every website and when it's done it reports on the website info and it passes that results in which is the website data model so that does is it just writes out to the results window text it appends the URL and the length of the data and fine at the end it writes a new line then we have one entry per line so that's that's all we're doing is we're just grabbing a whole bunch of URLs one time we're downloading them and reporting the information to the screen now that's kind of important we download web one website enter your port ID I think of the next website and download it and report it so let's see how it actually works now just know the first time you run this it's a lot slower than the second time and that's because it's actually going out and trying to find the the proxy settings the first time after that or members it until the app closes so the second and third time it's a lot faster but will ask you the first time and I want the first time I should observe two things first of all I'm going to try and move the window after I click this button and it won't move and second of all I want you to see if those lines come in one at a time or all at once at the end all right so here we go click the button try and move nothing happens and there boom all those lines popped in all at once till I see fusion time this is in milliseconds so it's two point two seconds so there's the websites there's how long they were now notice if you execute a second time the it changes a you know one point two seconds even down as low as 0.7 seconds so it's it gets it gets pretty fast once it gets past that looking for the proxy server but that's where we're at somewhere around three cords of a second to download these six web sites so let's see if we can't do something with these two problems problem one I can't move the window around while it's running problem two is that these show up all at once at the end instead of one at a time as we get the data back so let's let's address problem one first because I'll show you there's there's two different parts to asynchronous and I'll make sure that we kind of separate them out into their respective parts so first let's essentially a copy of everything happens in the execute sync click and copy this whole thing and paste it down here the one thing I'll change is we're going to run download async now it doesn't exist yet but we're gonna create it so let's kind of minimize some of the other things we don't need and we're actually not again copy this the run download sync and I'll just paste it here and say async ok so we have exactly the same thing as before if we were to run this it would run the same way both times but let's see if we can't make this work a synchronously so that we could release that user interface and it doesn't lock up while it's running now if you know anything about the download website method you'll actually know that down here there's actually a oops not download website here we go inside here the download string for the web client it's actually a download string async or task async actually we're not gonna use that yet we're gonna wait I'm going to demonstrate how to do it if you can't change that because sometimes you have a lot of people's code or Cody just can't touch but you want to have it run asynchronously and so how do you do that and so I'm gonna go ahead and do that for you just kind of show you what you can do to make this run a little better a little bit a sync rest so we're going to do is take this line right here where it says let's minimize this we don't get confused this line right here with has download website and then pass in the site let's pretend we don't have control over that but we want to make it asynchronous so the way we're going to do that is right here sa task dot run and what tasks that run does is says I want you to sit run this stuff in here inside my parens I want you to run it asynchronously now we're going to do is pass open closed another set of prints so notice to opens here open open close and then we're up do a lambda expression so it equals greater then and say okay pass in this code right here to run as our task alright now right away it yells at me now don't panic here since I'm saying tasked outrun knows what was gonna return back is actually a task of type website data model alright that's this right here that's the return so if they return a task of website ml not website data model which is what we're expecting so what I've done here is I've kind of wrapped this code in a asynchronous bubble but now I want to use what's called the await keyword now what a weight does is is okay you need to run this asynchronously but you need to wait for it okay and the reason why I want to wait for it is because I need to have these results in order to report on them so I can't go on report on something that I don't know the results of yet so we have us a weight keyword now it still yell at me but the reason why now is because saying you can't have a no wait operator unless it's an asynchronous method we change that if you say asic up at the top yeah that's all good now here's one one tip right away and don't worry it starting it lost a little bit we're gonna go over all this over again but I want to get it all out here first so real big important tip here don't return void from an asynchronous method if you don't have anything to return don't create something just say tasks okay now if you do have something to return say it was actually turning a string what you do is just say tasks of type string and now that's saying this is gonna return a string so return yep or whatever and that works now these return string not you don't worry about wrapping and tasks that's taken care of by this async but in our case we don't have a return type it was returning void so now we just say return tasks okay so make sure it does not return void now there is one exception of that and we'll see him to submit it but ain't any hood event you can't change an event from void to task it doesn't work that way so you have to leave it void and that's okay that's like that's fine that's the one exception that c-sharp knows about and it is fine with all right so let's go back and look at our run download async and just see what what changes we've made first we've made it an asynchronous method and then we said it has to return a type task now the one more thing I didn't point out but it's it's actually a really important convention that you really should follow and that is you always append async to any method that's going to return asynchronously now in our case we had sync and so async can't make sense but the reality is normally a be run download and run download async so just make sure you append async on the end just let everybody know this is actually an asynchronous method not a sync rs1 all right so we have async return the task type task not type void and we have the awake keyword in here and again a weight keyword says run this asynchronously but wait for the results may may be wondering well why would you do that because it seems like if you want to run something asynchronously you shouldn't also wait for it that kind of doesn't make sense remember our ABCD tasks example you know if we're waiting for task B before you do C and D what's the point when I just do a synchronously and the point is that whatever caller calls this can go on with their work after calling this okay at the very least our user interface can get back to doing user interface work while this is running even while we're waiting for it so it kind of it kind of puts in the queues is okay we're waiting for this it's not done yet so you go ahead and do your work and then it goes oh you know what I have got that results I'll go ahead and process from here and so it allows us to have a little bit of flexibility a little bit of control back because it's running asynchronously so all they did was wrap our call the download website in a run task that run had the open closed paren lambda expression the actual command we were calling you for wrap the whole thing in parens for a task that run that's it okay let's see what the difference is then I remember this is running asynchronously inside of our execute async click okay now this right here is warning me it's saying hey you're not a waiting for anything here therefore it's gonna continue on afterwards I'm gonna leave that for now but I want to show you what happens but we'll get back to that warning and and fix it but for now let's go ahead and run this now I'm going to cute my async first we remember it takes a little bit longer the first time so I want to have it tied I'll show you I can still move the window around so let's let's click here and now I can move around and look at that they're popping in and I can move my my thing around at the same time but I want you to notice one other thing right here total execution time too and then after that I have six websites have been downloaded so that's a little weird because it stops my timer before it finished all this work I'll show you why because we never said wait for this we done therefore it said okay it's a fire-and-forget call it we're not worried about it therefore I continue on where I stop the timer we're at give us a lap in milliseconds where I write that out of the window and we're all good to go and this is where people usually panic and say oh no i've broken async/await I don't know how it's gonna work it doesn't work for my application because I can't just fire forget these things so what's gonna go on well don't worry okay we're gonna we're gonna fix this all I'm gonna do is say oh wait it's real wait for this now don't forget whatever you do await you have to do a sync now I'm not changing the method name here and I'm not change this from void the reason why is because this is an event therefore I don't change it from void and I don't change the event name because it would break the event I could go through and put click async but it's an event so let's let's leave it alone all right let's try this again and say execute async move it around it's fine there pop it in one at a time there we go now let's run both of these over again just to see the time difference so execute i sync again that's 13 64 8 33 1193 854 some around there execute normally by second 710 second 1.1 seconds 0.9 seconds they're both executing about the same speed okay so let's see if we can't get these tweaked a little bit to work at different speeds so let's take advantage this executing in parallel now the reason why they execute the same time or the same speed is because of this right here via weight what we're doing is we're calling a first website saying download that but wait for it okay now that's what it does is it blocks this particular method from going to the next website until this first one's downloaded and then it goes to the next one and it blocks until the next one is download so let's solve this by actually copying this method and we'll create a new version of it mmm eyes that one down we'll call this one run download parallel async so it's gonna do all these tasks in parallel instead of in sequence and away each one okay so let's create a list of type tasks of type website data model alright and we'll call this tasks that's it that's a pretty complicated list let's look at it so it's at the very heart of it we've got this website data model and that's what's returned from this download website but remember that if you don't await it it returns a task of type website data model which is this right here and I'm saying about a list of those because I have a list of websites I want to download so now let's get rid of this line right here where your report on something and we'll get rid of e a weight and now we have this where it turns a task of website data model we have this list of tasks a website data model so it's going to say tasks right here tasks dot add and add that one task so what this is is it's saying I've got this bit of work it's kind of this this bubble of work that I'm gonna do or I'm trying to do where I'm working on but it's not done yet and so it's gonna put this in a list so now lists these little bubbles of work these little pieces and they're all running at the same time and then at the end of this I'm gonna have this list of all these sets of tasks they're running or have completed all right so we're gonna do down here is save our results equals a weight task dot when all so what the when all does it says I'm gonna pass in some tasks a whole set of them well be you know one or a hundred and you just wait until all of them are done and when they're all done then I want you to pass those results back into this results variable so that that results variable is actually an array of website data model now I'm more a fan of a list instead of an array that's not a big deal because for each still works on it I'm gonna say for each for each item in results and what is item item dot there's the website data and the URL so now I can use that that method we have report website info so I can grab a copy of that and come down here and say report website info for item so you see the difference here before up here we're saying do this task and wait for it and then do the next task and wait for which which works and it's asynchronous which allows the user interface to get control back and allows us to show that line one at a time instead of all at once but it still meant that we're waiting the length of the some of the download times so you know if each of them takes three seconds and there's six of them that's 18 seconds where the download time whereas here or doing is saying okay I've got a list I want you to download it next one download it next one download it now all they're doing is grabbing that task back and saying here's this little bubble of work it's already turning away downloading that website just kind of hold on to it and we're putting those those bubbles of work in this tasks list then we're saying you know what when all of them are done grab the results of all of them loop through them and report so what's gonna do is it's kind of kind of wait to show us until they're all done but they'll ask you much faster okay so there's getting a little bit of downside missed method and in fact there is a way to do have the best of both worlds but that's for the the next async video I do where you do some more advanced stuff like reporting back from an asynchronous method into your user interface which could be a little complicated but we'll break it down for you but that's not in this video so just know that you know for this we're gonna kind of lose some of our one at a time showing it off kinda thing but we are like gain some speed by doing these all at once so let's change our call up here in our event execute async from run download async to run download parallel async and let's run this again and we'll do the normal X actually let's do it X async execute now remember it downloads so the first time let's click it and boom it's done total execution time remember this is slow at 789 let's do it again 385 379 293 373 let's do normal 792 11 hundred a thousand 800 793 async - 47 to 52 - 41 so you see the difference there we've got that speed boost now because each of these websites is downloading at the same time that means in general we're waiting for the longest website to download the slowest one so an Omega that was pretty big it's got two hundred and nineteen thousand characters Stack Overflow has 256 thousand so probably one of these two is the one we're waiting on and so these other ones may have been done parked there just waiting until you know these to come back and once one you know the both of them come back then the whole thing is done versus every weights for this whole thing to get done then you go onto this next one and that's next one this next one this next one you if this whole thing you had done before you're done the whole thing that's why normal execution time takes you know a thousand eleven 100 milliseconds versus half that time or less third that time so as you can see there's a big difference right away in my application so let's recap what we've learned so far first of all the the basic keyword here a lot the ones we that deal with are a sink and a weight a sink marks a method to say this is an asynchronous applicator or asynchronous method and be oh wait is what we use to say wait on something wait on some kind of asynchronous method and the reason we use that a wait is because if we don't then we're gonna fire and forget it and go on to the next step which is what we had when we saw that the timer was written first was a timer continued on while this was downloading the websites so he had to say nope wait for that but even though we're waiting for something it still gives control back to the user interface so that we can move it around we can see other things pop up other things could happen in fact we can even have other events kicked off or other tasks done by the user while they're waiting for this to complete so it really does make much more use of your operating system much more use of your your hardware of your computer because it can we do a whole lot of work and yet still give the users the experience of a responsive application no one wants to have an application where they can't touch anything well something's running you know I just kind of locks up it may even turn gray got the you know the spinning wheel or the the hourglass some like that that's just not fun so this way just saying a sink in a weight allows us to avoid that but then we also have the idea of running in parallel where we're doing multiple tasks and then saying hey when all of them are done then go ahead and move on in this case a weight for all of these and then afterwards print out the results now the one thing I mentioned earlier that I kind of not made up but I kind of demonstrate how you could do it when you can't touch a method is this tas run it's a task outrun wraps around a call to make it asynchronous when it's not asynchronous but in this case we do have the option down here in the download string to change that over to an asynchronous call so I could do is I could change that let's copy it and paste it and this time I'm gonna say download website async and I'll make this call right here download string to download string task async and I will await it and then finally I can make this method asynchronous and return a task of type website data model don't forget to change it to task and why task well remember when we return back an asynchronous method but just say keep going we want to have that whole that whole bubble we're saying I have this it's working it's running and I'm moving out I'm holding on to that so that later when it's done I can do something with it and that's what we have to have it be a task so that that's a task of type website data model so I'm using the the built in and they gave me tasks async so that's great all they need to do then is come up here to my run download parallel and change this to instead of tasks that run I can just take that out and say this is the website download or download website async that's it so since it's already asynchronous now I have to do that that tasked out run stuff I need to pass that into my list so it works the same way we run the async execution boom you know it still works just like before it's just that I don't have to do that task that run so that's if you have control over the method and can make it asynchronous natively that's great and go ahead and do that but if not don't despair you can just wrap it in a task dot run and then you're good to go so a little more of a complicated subject in some ways just because you got to kind of think about what's happening and plan for you know do I need to make this async don't you make the next level up async don't you wait something or not wait something but but but the basics are whenever you have an oh wait you should make it the method async you have to make the method async let me make the method async you should change it from whatever output is to an output task of that help that type so task just its own if you're returning void or task of string tasks of your model whatever so those are the big things to remember when it comes to a synchronous and then do you want to await something or not await something you don't have to await something but just remember if you don't know wait wait it it's going to first will return a type task or whatever output you wanted and second it's gonna allow your code to keep going just like it did with our stopwatch they kept going they hit the stop and K is the elapsed milliseconds of two milliseconds which sounds great except the fact that that's not actually how long it took it's just that's how long it took to fire us off and keep going so when to use a weight is whenever you need to rely on that data coming back o or use that data coming back or your application shouldn't go on until it has that data that's when you usually wait all right so async await we have tasks and that's about it for asynchronous programming it really is that easy there's no worrying about apartment models or you know threading contacts and contacts switching all the rest of stuff that we used to deal with a lot of that's wrapped up in just a sink a weight and tasks those three things so if you see some examples online where you use this some that more complicated stuff don't worry a lot of that's kind of hidden behind the scenes using this just a sink in a way I hope you found this valuable like I said there is a part 2 coming that'll be the more advanced stuff like cancelling a task mid tasks and also getting some information back out of the task once it's running so some status updates that kind of thing so I'll have that more advanced video for you in the future in the meantime I love if you leave a comment below and let me know you think if you have any questions that you'd like to answer in that second video if it's not out yet but I'm you see this go ahead and leave those in the comments down below as well and I'll try and get back to those and and respond to those in the next video all right also in the description is a link to my mailing list if you I alerted to some of my paid courses and the discounts that the only mailing list people get then definitely go ahead and get on the mailing list alright thanks so much and I'll see you later
Info
Channel: IAmTimCorey
Views: 609,542
Rating: 4.9537859 out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# training, C# tutorial, async, await, task, task.run, asynchronous, threading, context switching, c# async await, async await, parallel, asyncronous, wpf, best practices
Id: 2moh18sh5p4
Channel Id: undefined
Length: 38min 57sec (2337 seconds)
Published: Fri Jan 26 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.