Developing Multi-threaded UI Application in WPF using BackgroundWorker

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
voltage setting is a very important aspect of UI base applications we will discuss that how we can develop a multi-threaded application in WPF and I will be demonstrating a very small application with the help of background worker and this application will actually create a counter and this application will be responsive when we are actually running this task and we can start this table this and he started again and this is this is all done with the help of background worker in WPF so let's see why do we need this and how we did this with the help of background worker so the question is that why do we need multi-threaded applications or UI multi-threaded applications so the problem is that whenever we are performing some lengthy operations such as lengthy loops we are looking for the user input on a port listening on the port and may be searching for the file system and processing some files reading some large files even writing some big data in files and even doing some operation on life server reading or accessing the life server and sending a request and waiting for the response so for these kind of lengthy tasks some of them they are not predictable that how long they will run and sometimes we don't know that how much long will it take to complete the task for example if I'm scanning file system for searching for file different file types and I don't know that how deep is the directory structure and how deep I need to go and look for the files and similarly if I send a request on a web server I need to wait because I don't know how long will it take to get a response from a web server many factors are connected with this type of request so in that time meanwhile when you send the request your UI will mean unresponsive it will not respond to you while you get response it's just like this that when you're when you are running a code when it completes the execution such as in event-driven programming when an event is the execution of that event is just completed you are done and your UI you get that is false back to you and then you can perform that operation again and again and again and so on but the problem is that for example if we are working with large loops in this case if you see that example over here in this example if you have a lengthy loop which is this code is written behind that button click until and unless this loop completes the execution button will remain in a pressed state and will not get back to the normal state and you your application will help and will not respond to you you cannot perform any other operation so here is an example of simple multi-threaded application that we want to build so let's see the what kind of problem we are in in this application a small application we have label we are not using it right now but we will be using later on but just to demonstrate the problem we have button over here and this button has a click even handler so if I write a lengthy loop over here let's say for example a long loop and meanwhile if I let's say just control console console.log so I will just write line this counter and just to see the outward and put the delay of this counter so that I can kind of simulate the problem that what kind of problem it is I will just sleep the current thread with the help of thread class and I will sleep it for 1,000 milliseconds it takes the argument in an integer which is in milliseconds of 1,000 millisecond is one second so it will wait for one second and we'll continue this loop so let's assume that this is not a doob this is some kind of large process which you are going to perform behind this button click that can be a knitting request to a web server listening on a port for an incoming connection or maybe you are processing some large files searching for the filesystem this can be any long process I am just putting a Louvre just to see and just to demonstrate that what kind of problem we get in our UI based applications when they are not multi-threaded application so let's run this so here is my output window and if I start this you see that it's printing this counter and the its executing and ready sleep for one second after every one second it's presenting you the output now the problem is that my UI thread is held and it's not responding because it's currently processing this piece of code and I cannot perform any operation I cannot even launch it back and the button is still in the pressed state and will not end this execution whereas if I have a data for example smaller loop let's say for example just for the five digits and I sleep for the one second and when I press Start you'll see that counter is coming and this button is is Hank and now it's again in the normal state so if I press it again now it's in a press state and now it's a normal state so if I press it again I cannot not I cannot even this window even now you see it's moved like this so this is the problem so we want to perform such a heavy task and such such a task that is longer and will take much time in a separate thread so that our UI remain responsive and child process will execute this kind of lengthy processes so let's see how we can do this and WPF and in the.net UI base applications to perform such a multi-threading in our application we need to create a child process which can actually perform this task in separate thread there are several options available in dotnet and there are many options such as thread pools such as a thread class and there's also one option in dotnet framework which we can use and build our multi-threaded the UI base application with the help of background work so I personally like back up background worker because by Oracle is quite easy to work with the UI applications and provides many functions in this we can actually update the user the progress of execution of the process and so on so let's see that how we can implement the background worker in our UI base application so background worker is actually available in system dot component model and system load component model namespace and this that's a class background worker class and it supports following events do work progress changed and run worker completed so these are the three events that background worker class triggers on different operations so do work is actually is the most important and the heart of this background worker class which is actually the main thread and the tasks that you want to do and lengthy tasks which actually makes your UI not responding and makes your UI held and this is the task that is the heavy lifting to ask that you will perform in a do work event progresses even will be used and will be triggered when you report the progress or the report progress method is called it is used to update the UI based on the current process for example you are scanning like hundred files and thousand files and you want to show a progress bar and you want to update the user that I am scanning this file I'm reading this file or I am writing these files so you want to update the user that what's happening inside this do work lengthy process so you use progress change and progress change even is triggered as soon as you report the progress with the help of report progress method and the third event is triggered when the new work actually completes the process the execution of the doer completes as soon as it's done when were completed is triggered and you can show the users some some message that if example finished I have scanned that much files and I got that response from the server and so on so these are the three events which are the very important and the most important in background worker class do work progressing and run worker completed so if you are working with the WinForms development background worker is available in your toolbox as a component over here and then you can actually track and drop that on your form if you are working on a min form and it also provides some properties you can add events and the two most important properties are worker reports progress and worker supports cancellation if they are true then you can actually report progress and the progress change even will be triggered and also supports cancellation which means that the process is running if from if a background worker thread is running you can cancel that thread and if that is allowed in your thread you can cancel it otherwise you cannot do this so these are two properties which is actually of type boolean and by default they are false and you need to make it true so that if you want to your worker to report progress and if you want your worker or the background worker to to be able to cancel the execution at any time there are also in WinForms there is also a UI in the properties you can add events just like we have in our normal applications with the components so these are three events directly available in the property window or the events window in the wind form but unfortunately these are not available in WPF so how do we do this in WPF you don't need to worry about it it's easy to do this in WPF we just create or we just first import the system dot component model mean space and we just declared the object of a background worker and we can after creating the object we can actually add do work progress change and run worker completed events by our own so by adding these events these events will be added and we can actually write our code inside these events and we can work around and similarly for the for the properties we can also do this work reports progress we can set it to true and it will allow worker to background worker to report the progress and if if you want to support your worker to work with the cancellation if you want to cancel it any time stop the execution anytime and most of the time it's required and you can make these properties true through the object of background worker so that's how actually you work with the WPF and the background worker so let's recall our problem so the our problem was that this is a lengthy process that we want to do this and perform this in a separate thread so that our UI remain responsive and this should be run this should be executed by a separate thread to do this we need to perform this operation inside the do work even callback function so to run our code or to run the the multi-threaded process with the help of background worker we have created the object of background worker and the class level and we can call the run worker async method as soon as you call this random worker async method it will trigger the function which is due work event so all the process that you want to perform in a separate thread you need to put that code inside the to work a callback function and you have added this event as an even handler so that's how you can actually start the bagging on worker and this is the very basic example of background worker and if you look back into our problem we can solve our problem which was actually the halting the UI now our UI will not be halted and all the data will be printed on console and meanwhile we can actually work with our application and we can perform other operations while this operation is performing by the application so let's see how we do this so this was our program where we had button and behind that button we are actually running this process and we now need to convert this process as a separate thread so that our UI remain responsive when we are actually working with this so for this I can first clean that up to remove and sort usings so I will remove the using which are not in news so I will add system dot component model namespace and I need to have a background worker object I need to create that object and I can create this at class level so background worker let's say for example BG worker is equal to new background worker so I am just creating the object and if you remember we need to add three even handlers for background worker so ve sorry so as soon as we initialize the components we will add background worker events over here so do work is the very power and most essential even at and if you see that it's saying that you need to call run worker a Singh so that new work will start the execution so I will just add this I will press tab to insert this worker and I will put the implementation over here inside this so our heavy lifting task which was actually making our application not responding I will put this task inside do work and when I press the button I want to start the thread so to do this I need to call run worker a Singh method as soon as I call run worker a Singh method it will run or trigger the execution of do work so let's see that how we do this and what would be the output so now if I press the start button it's starting the counter and you see that my application also responding right you see so if I were to clean this up and start it again so as soon as I start it's running a separate thread and it's working I can also do this little more things on this so let's see that how we perform other operations with this so another thing is that how about if I press the start button twice so if I press restart and then start again now we have a problem the dot background worker is currently busy and cannot run multiple tasks concurrently so to perform multiple tasks we need to have a separate background workers or we need to handle something over here in the new work so when I press the button it's actually running the task again and trying to call this do work and want to start a new thread to handle the situation we can actually check the background worker that if it's busy or if it's not busy then we actually run the async run worker async method so if it's busy we will not do this if it's not busy then we will run this task otherwise nothing will happen maybe we can show a message that it's already running and it needs to stop and something like this so if I start this and start this again nothing will happen because it's busy already and if I start again it will start the counter again and so on so how about it would be very nice if I run this and as soon as I run this I change the text of this button with the help of content property to make it stop okay so if I run this and if I start now it's Singh stop but it's not stopping this the thing is that if I want to stop this I need to support the cancellation right and I need to have an even that I can add later on but the thing is that I want to cancel the execution as soon as I stop this so if the worker is not busy which means that it's a in a stopped state it's a it will change the text to this stop and what about if my worker is busy and if I press the button where the content would be stopped I want to stop the execution of this so for this I need to cancel a sync so request cancellation of a pending diagram operation the process which is running I want to cancel this so to cancel this I need to call this function so when I call this function it only works if I provide the cancellation option with the background worker object so again I am writing over here I'm wrong so BG work at dot worker supports cancellation is true yes we can now cancel the the execution of this process and time and this will actually tried to cancel the execution so let's see are we done with this will it stop the execution of Newark so start stop nothing happened it's still running because the thing is that we need to handle this or we need to check that if the worker has sent a request for the cancellation so I can check after this over here that if my background worker object has requests for the pending cancellation or not so cancellation pending so if there is a cancellation cancellation pending I can actually break that loop so this break we'll break this loop and we'll act with the counter and I can write maybe a console message so that you can see that it's actually executing the or the breaking the loop so the thread is exiting not say so if I run this if I press the start it will start the new work if I press the stop thread is exiting all the text is not changed I need to change the text over here so that when it's done with the cancellation it will turn back to the start so if I press the start it's running over here if I press the stop thread is exiting if I press the start it's starting from the beginning if I press is stopped it stopped if I press the start again and if I press the stop it stopped so that's how actually you can run the thread and you can stop the thread already executing the thread so cancellation pending is a very nice thing because maybe over here you are executing and writing some files reading some files writing something into the fire so there must be a very safe place where you exit the thread but you cannot just just abort this read Because aborting the thread may cause some stray pointers in your file system and then maybe you are your your program is a in a state where you have opened the file but you did not close the file so it's important that once a cancellation request is sent you can check in your code that where do I want to check the cancellation pending and then I can actually stop the execution of the of the thread or the do work process so that's how actually you start and stop the thread so let's move our program from the console to the UI so that we see the counter and inside this label so to do this it's quite easy that instead of writing on consoler maybe we can also write on console and we can also put this inside this txt box which we have so real able we have they will counter dot content so we actually change the content every time with the new content so we are actually updating our UI with the help of background worker so let's see how we do this so if I start the button it should start the counters right the counter and on console and also should update overhead so let's see other it performs this operation or not so we have a problem over here that calling thread cannot access this object because a different thread owns it so here is an important thing that you need to remember that whenever you are running a UI base application it's running on a separate thread and the cross thread the other thread who is running some process you cannot directly access the elements of other thread in this way there is a proper through proper channel way and adopting that way you can actually access the other thread or the UI thread in our case so in this case we have events available and functions available will which will be helpful in updating the UI so that's why in the beginning I told that I like background worker because it's quite easy to update the UI as compared to other options in dotnet framework so let's see how we do this so we cannot access the UI thread directly inside do work but we can access this UI element inside the other events which are available with the background so these events are progress changed so progress change event is something that we need to trigger and we need to update the UI so instead of doing this over here we need to do this over here and how this event will be would be triggered we need to do this through a calling a function which is a background worker function which is reports progress so when we report progress we have two options over here we can send the percentage of the progress we can send the state of the object over here as well so it also depends on us so when we choose the percentage so percentage could be from zero to hundred 100 it actually used for the for the processes or for the function that we are going to perform in our application way when we know that how much elements we are going to process so let's say for example I am reading 100 files or writing 100 files I know that I am processing 100 files so I can actually tell that I am reading file number 25 right now and we can also send with the help of the other argument which is an object time it means that we can send anything maybe we want to send a file name so the first argument will only be used to send the percentage and the second argument can be used to send filename in this our case the situation that we are right now we cannot actually we don't need to send the user straight or the second argument we can actually send the percentage in this case we are just sending the the counter over here so I will send the counter over here and I can get this percentage from processing even argument and I can receive both things the the state object and also the progress progress percentage property as well which is returning me in the present age so in this case we are just receiving the integer and I am sending or assigning this in danger to this content property so as soon as I call this function report progress it will trigger the progress changed and progress changed event can directly access the UI elements so let's see how we do this either we achieve this or not so if I run this and if I press the start it is saying the background worker State does not report progress which means that progress reports is not allowed by default at 4:00 I have told you in the beginning that worker sports cancellation is by default is false we need to make it true by ourselves so also worker supports reports the progress the worker can report the progress now and as soon as I report the progress it will trigger the event and DUI so you see that it's now updating the UI and it's not a problem I can do that and stop at four because the loop is less than five starting from five from zero tailless it much so I can make it a bit more sensible so I can also reduce to the half second or maybe less than that and maybe increase the counter to a larger number so if I start and now it's running and it's also pending on console and I can actually move this application this application is running fine I can open and see the progress what's happening over here I can stop this I can although when I start this again it will start from beginning but my thread is working and it's updating the UI so that's how you do this and we can also work on this so that if I instead of stop I can put a pause option over here I can add more buttons over here so that one button can be used to pause and one can be used to reset the the counter like this and I can increase the speed of that counter as well to make it legit for that but 100 milliseconds so let's do this now you see the counter is running and it's responding and it's updating the UI with the help of background worker so another thing is that when the counter is complete when it's done it it's again showing the stop the often over here so to do this we need to add an another even-handed which is bid you worker dot what run worker completed so this event is triggered as soon as do work is done with the execution so as soon as this for loop ends and the body of the doer completes it triggers the completed event so it will trigger this and I can change the content of this start button to make it again to start so let's make a loop a bit smaller so that we don't need to wait longer time so let's make it like 10 so if I run this and if I press Start Singh start first so another thing is that if it's not start and it's completed or finished and if I somehow run this start and stop when I stop this actually I stopped the execution by myself it's not actually completed the execution so I stopped or I actually canceled this so how can I figure out that this was actually the operation of cancelation instead of actually completion so to identify that I can go and I can tell that when I am cancelling the progress I can tell this even that I'm actually cancelling this with the help of e dot cancel which is doer even argument so with the help of this I can actually tell that it's cancelled it's not stopped and I can actually check it over here with the help of E which is even run vertical completed even argument so a dot canceled if it's cancelled I want to say something else over here so I can say that stopped make it a bit bigger so that we see the text so if I start and if I stop it says that it stopped although I just stopped at the tenth so if I stop it's a stop so if I if I keep it like this let it complete it's saying completely which means that we can also identify we can differentiate that when the the progress was actually stopped user has canceled the copying of files and the requires and scanning or user actually or or the process finished itself which means the do worker actually the execution of do worker ended by itself through the normal execution or user actually cancelled this so we can actually take the help of even argument and we can tell that I am actually cancelling this execution which means that I am actually trying to break this group and getting out of this - but this even argument this event will would never know that either it was this loop was broke like this with the help of break or or actually it was completed so we can actually send a signal from here from a dot cancel and we can actually identify with the help of e dot cancelled so with the help of this we can actually differentiate between that and depending on upon that we can display the appropriate message to the user and we can identify that either this process was completed itself or use it actually stopped the execution so that's how actually we do this just to add few final touches to our counter application I will just make it a bit more sensible so I will actually instead of adding this button and putting the text over here I will actually make this counter as as a status so I will put a status over here initially this there is no status and I will actually use that status and will update that stated based on the condition of the our background worker thread so I will use I will be l straightest dot content and I will say that and it's running and I will say that it's stopped and I will say that instead of the button I will use the content the status content now it will say the completed like this and it fills in the running and it will say the stopped and let's run this now so if I easy start saying running if I say stop it's stopped and instead of stop it should say the start so it should say the start in anyway and it should say the in the content it should say any stop so actually I will keep it as as stopped and I will say that it should use the status label and would update the status label with this stopped and in any way I will just make this button BTN start content to start because we are notice we are maintaining two states stop and start that's it so when I say start it's updating the status it's running so as soon as it completes it say they complete it and again the button said the button text is start so if I stopped in the middle it say they stopped and again the button state is start you can try working on this to make it pause and start and can take add an another button which will actually reset the counter and so on so you can actually do this stop and start stop and it stopped and if I say start it's turning and I can stop it and it start we can also make it like this that I can give it a pause and instead of start and stop I can pause it so it's all up to you that how you want to do the functionality how you want to implement the functionality it's the last thing I want to show you over here is that the progress bar so I can add a progress bar over here so let's add a progress bar like this so progress bar has a property which is the value I cannot type it right now so it must be inside the common so this is the chain and the maximum and the minimum value and the current value is zero so initially the progress bar has no value so I will give it a name so that because I want to change the the progress bar value so I can call it progress bar so as soon as I update the UI I also want to update the progress bar so this dot progress bar dot value which is a type of double so I can actually retrieve from the progress percentage which is which is an integer and I can assign this value to this in this case we have the maximum value is ten but progress bar actually works from the 0 to 100 value and if you see when I was selecting this it's it's it has a maximum value of 100 so I can actually change this to 210 as well and I can choose that how much progress I need to show and what's the total number of elements i want to process and show that so this is the progress bar it's also increasing depending upon this so it's out of its showing 10 failed 10% failed out of 100 so I can actually modify this as well to make it maximum or maybe I can do this programmatically over here so I can specify the the counter max value counter max is 10 let's say and I can use this counter max over here this dot it's it's not at the class level so first I will make it at class level but I can actually initialize it over here so I will use a counter max over here like this and I can change the progress bar maximum value to this dot counter max so whenever I change the maximum value of a counter progress bar maximum value would be accordingly so if I press restart so it's the maximum value is 10 so this is the complete value over here and if I change the max counter I can also make it a constant so that I cannot modify it later on let's make it 100 and if I speed up a bit by 100 milliseconds and if I run this now so it will update the progress value there it is here it is it will update the progress bar value as well so it's running and I can stop it I can start it running and now the maximum value is depending upon the value of this counter max variable so I'm actually dynamically changing this depending upon this okay so that was the last thing that I want to discuss that's how we can actually work with the back door okay so that was all about the multi-threading with the help of background worker in the WPF application we have been very small application in which we actually used the counter and the counter works with the start star with the progress bar and in straightest and we can stop it any way any time and we can start it again and my application is responding a UI is not heard and that's how actually we do this with the help of background worker in WPF you can try working with this you can receive this code or download this application and the code from the github account and you can work with this and you can actually convert this application into the to contest one counter will be used for the increment counter and another counter could be used for the for the decrement counter and you can also work around with another type of applications let's say for example you want to generate random number four four kind of poll and something like this and you want to actually generate a random number for the drawers and like this and you can actually work with this kind of application you can develop this kind of application so that you see the list of registration members and see your numbers rotating in front of you and then you can actually start and stop and you can take the drawers and like this and you can develop this application and WPF at the help of background worker it's easy bagger worker is got easy working with the UI applications and that's all actually we work with this and we learn this so try on your own and practice this and see how you can develop your applications multi-threaded application in WPF with the help of background worker
Info
Channel: Code Synergy
Views: 7,239
Rating: undefined out of 5
Keywords: WPF, Multithreading, Multi-Threading in WPF, Background Worker, BackgroundWorker in WPF, System.ComponentModel.BackgroundWorker, ProgressBar, UI Halt Problem, UI Not Responding, Threading, Threads, Multi Processing, Update UI
Id: snkDYT1Qz6g
Channel Id: undefined
Length: 47min 38sec (2858 seconds)
Published: Mon Apr 27 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.