Welcome back.
In this video, we are going to look at tasks and specifically when working with DWP.
Therefore, let's create a new project and let's use WP F here and I'm going to call it WP F tasks and
EE in my case.
Then let's press OC to create that project and in my UI now let's add a button and I'm going to do that
through the toolbox.
So I'm just going to select a button and drag it into my UI.
So there we are.
I'm just going to make it a little bigger and let's change the font size to 32, maybe something like
that.
Now it's a little easier to read and I'm going to give it a name.
Name is equal to my button because I want to use it later on in my code behind.
All right.
So that's the UI.
For now, we are going to add a little Web browser later on, but for now, the button is going to be
fine.
And in my main window, I want to use that button, but I need a click event, therefore.
So whenever somebody clicks on that button, I want to download something from the web, and once it's
done downloading, I want to assign the HTML to the button text or to the button content and therefore
I need a click event.
So I'm going to double click on the button and it will create a new my button click event here.
So this method is going to be triggered whenever we click on the button.
And the easiest way to see if that's true is to just use a message box and just say something like Hi
or it worked or something like that.
Now let's run it just to see if our code actually works.
Because before we do anything else, let's just see if Button works and it says hi.
All right, that's fine.
Now, as you can see, the text itself is not really as big as the button text.
That's not pretty.
But that's not what this video is about.
Right?
It's about tasks and it's about downloading something in the background while the UI is not being stuck.
All right, so let's find a way to make it stuck.
So let's go ahead and try something like downloading.
And in order to download something, I'm just going to use an HTTP client and I'm going to call a web
client.
Now, HTTP client is a class that we have to add system dot net, dot, http.
That's what we need here.
So this web client now, it will be a new HTTP client and now I want to have a string which is going
to be the HTML, which will be web client dot get string async and which string shall get well, it
should get the https.
Colon forward slash forward slash google dot com.
And I want to have the result of that.
So download website and give me the result and store it within HTML.
So that's what this thing will do.
Right.
And what I'm going to see is the thread that I'm on.
So I want to see the thread that I'm working on.
Right line is going to be thread number and thread dot.
And in order to use thread, we need to.
Use system threading and in order to use debug we need to use system diagnostics.
So let's do those two things and now we can go ahead and get the current thread and the managed thread
ID.
So I just want to know which ID does the thread have that I'm currently running on?
So when I click the button this debug will be printed and it will download something.
Now let's say I want to change the button content so my button got content to something like done.
So let's test that.
There we are.
Once I click on the button, you can see now it's done, downloaded it and it's done.
And that happens because this one here.
So downloading Google.com actually works pretty fast and that's why it's even possible to do the content
equal done.
But usually that shouldn't be possible or in most cases it won't be possible because this task here
usually takes quite a while.
And we have a thread here that is quite, quite heavy because downloading stuff usually takes a while
and except it's very, very little that we are actually downloading in this case, we're just downloading
a Google dot com website which very, is very, very short.
It's just a couple of kilobytes.
So instead I'm not going to download a five megabyte file.
So it's a little longer until all of that is done.
So let's check it out again.
I'm going to press the button and now you see it freezes.
And only once it was done, it changed to done.
So maybe the 25 megabyte file is too small.
Let's make the 200 megabyte file.
Let me actually check if there is one on the website and there is one.
All right, let's try it again.
Now, the file will be a lot bigger and will take quite a while to get it done.
So I'm pressing on the button and as you can see now, it's freezing, it's frozen and it doesn't have
anything until the download is done.
And that's because we are on the third one.
So the whole screen is frozen until that download is done and that's something that is very dangerous.
You should not do that.
You should always be careful when doing stuff that's heavy on the main thread or on the UI thread because
the main thread or the UI thread is really busy with updating the UI.
So it does all the UI stuff and well now my file or my program is frozen.
Pretty much.
So I'm just going to use a 200 megabyte file.
Maybe that's a better choice and that will be done and we will still see the difference.
Right.
So I just have used here a link where you can simply run or download random files.
So let's press it again.
As you can see now it's frozen and it will take a little while until it's done.
And there you are.
It's done.
So downloaded the file and it's done.
Okay.
And what you also see is that we are running on thread number one.
So that's the main thread, right?
And we're running on the main thread and we're trying to download something and we're trying to update
the UI and well, that's why it takes a little a little while here.
So now you might say, all right, let's create a task to do that.
So let's create a task that run and we are going to run some code in here.
So I'm just going to copy that code in there like that.
And now let's debug that.
So let's add a little debug point in here.
So let's go ahead and debug that just to see which threads are actually involved.
So I'm going to press the button and then we are we are inside of this thread.
And there we are.
So we have several worker threads.
We have the main thread, which is the thread one, and we saw that earlier on as we executed something.
So we have the main thread and then we have our task run which has a thread as well and we are in thread
five.
So you can see thread five is a worker thread and that's the one that we have here.
So let's go to the next step.
We're still at the, um, execution or still at thread five.
Then let's do it again.
Still a thread five.
And now we're trying to do something.
So we're trying to update my button.
Done.
And let's go to the next step again.
And as you can see, my application freezes.
It's evaluating expression, my button.
So we're waiting again.
So quite happy for it.
And as you can see, ma'am, that we are in Operation Exception.
The calling thread cannot access the object because a different thread owns it.
What does that mean?
Well, it means that my button is owned by a different thread.
And by which thread.
Well it's owned by the UI thread, which is our main thread.
So the main thread is responsible for taking care of all of the UI elements so that they don't freeze.
It's important that UI always responds, and in this case it's not responding anymore because we are
trying to access this line of code even though it's not in the right thread.
So we are in thread five and we're trying to access something that belongs to thread one and that's
something that is invalid.
So we get this invalid operation exception here and we need to find a different solution to manage that.
And it's generally a concept of different threads.
So generally you have to be careful when you work with different threads and with different objects.
If the objects are owned by other threads, you cannot change them or modify them.
So that's something that you have to be aware of.
So how can we do that?
Well, generally, let's stop the app first and let's go into button.
Therefore, I create a button here and I want to check out button.
So I'm pressing control or holding control and pressing on the button.
So a button inherits from button base, which is a content control which inherits from control, from
framework element from UI element.
Which is a visual object, which is a dependency object, the dispatcher object and that we are so it's
a dispatcher object.
And in here it just checks the access and verifies the X axis.
So this is a dispatcher object and we're using a dispatcher here and the dispatcher has plenty of variables,
events and so forth.
Why do I show you that?
Well, it's because we will use dispatcher in order to manage our thread for the my button.
So what should I do here.
Well, I need my button dot the dispatcher so gets the windows threading dispatcher the system windows
dot threading dot dispatcher object is associated with.
So now we find out which thread belongs to our button or actually which to which thread our button belongs.
So let's check the dispatcher and here I invoke executes the specified action asynchronously on the
thread the system windows threading dispatcher is associated with.
So that's exactly what I was talking about, what we need to do.
So let's go ahead and do that and let's execute the code in here now.
So I'm going to close it at the bottom there.
And now you can see now I can go ahead and say, okay, my button content just says done, and I'm going
to use the debug once again in order to see in which thread I am at this point.
So let's run the code again.
Now let's press the button.
And as you can see, we're in here now.
And now it needs to evaluate the load again so that we are so we in thread five.
Now this is where we do the debugging thing.
Then we go to the next thread or next line.
Next line and then the UI is back on track.
Where?
In here.
And now we can go to the next step.
So we're in the dispatcher and and here it actually jumps over what I wanted to show you.
So let's check it out.
Go to windows and let's see the debug console, which is the output so that we are it says thread number
five and then it said thread number one.
So this is thread number one and that's thread number five.
So the owner of the button, as you can see, is thread number one.
And in order to make that a little clearer, we could add that to our line here.
Thread number one or thread number, so-and-so owns my button, so now we'll be a bit clearer.
Let's run it again and then it should show correctly.
So here is the output and there's nothing interesting yet.
We press the button and you see thread number five was executed and then it starts to download.
And once it's done, once it's done, it says Here, thread number one owns my button.
So let's press again.
And now, as you can see, the button still works and it's still updating.
So that's good.
And that is one way of doing it.
There is another way, though, and I'm going to show you another one, which is a preferred solution.
So I'm going to copy this, my button click.
I'm going to call it my button click to just so it doesn't interfere.
And now I'm going to say at which thread I am outside.
So here which thread?
I want to click the button.
Well I should be in the red one then.
I'm going to use a wait task run and that task should be an async task.
So we need to add async keyword here.
Now Visual Studio is still not very happy, so I need to make this method asynchronous.
So this my button click now will be an asynchronous button method which will await a specific task to
run asynchronously.
And what I do in here is I simply download this file again, and instead of using a dispatcher, what
I can do now is I can actually update my button outside of this task.
So I'm going to do it outside here.
I'm going to say my button content and it's going to say something like Done downloading.
That's it.
So now instead of doing it with a dispatcher, which was a little workaround, I make it asynchronous,
so now it should work fine as well.
Now, in order to test that, I'm going to change the method here to click method to button click to.
Otherwise this method would never be executed.
So let's do that.
And maybe let's also add on which thread we are.
So thread number so-and-so before awaiting task.
And then this one is after a wait task and that one will be during a weight task.
So now let's run it again.
Let's press our button.
And here you see before task.
That was number one.
Then during a weight task that was thread number two.
And after weight task, it's at number one again and we're done downloading.
So that's a different approach.
That works perfectly well as well and that's even a better way.
So you don't have to go the way of checking which thread am I on?
But you create a different thread where you do this stuff, but and you also make it a weight.
So you make it asynchronous.
Now, a little something that I want to show you as well is a web browser.
So what I'm going to do here is I'm going to reduce the size of the button.
I'm going to put it here at the top left corner, and I'm going to use a web browser.
I'm going to just drag it in there and make it a little bigger.
So now we'll just have this web browser and it should show us the side that we're on.
So what will happen is whenever I press the button, I'm going to download a specific website which
I will define manually.
So this is just a little example to add on what we have seen so far.
I'm not going to go into a full on web browser.
I'm not going to show you how to do that.
You can go ahead and try yourself.
I'm just going to show you how you can now use that HTML that you have downloaded from this specific
link, which is hardcoded.
And simply use that so or display that in a web browser.
So https google.com.
So what will happen is whenever I press the button, google.com will be downloaded.
Now in order to do that, I need to have a specific method and I'm not going to type it out manually,
I'm just going to copy and paste it in here.
So this method on HTML change will be called whenever a dependency property will be changed.
So what I'm going to say here is on HTML, change needs a dependency object and a dependency property
change to event argument which is called E.
And here I'm just creating a web browser which is going to take that dependency object and use it as
a web browser.
And then if the web browser is not null, then navigate to a specific string which will be new value
as a string.
So whatever those dependency arguments are, property change event arguments are, that's where I get
the string from.
So that's pretty much just what needs to be displayed on the web browser.
So I would have done it in an easier way, but the problem is it's not that easy to do that.
So there aren't easier ways or many easier ways to do that.
So that's generally the approach that you would need to do here.
So instead of just updating the button with done downloading, I want to update the web browser and
therefore the web browser needs a name.
So I'm going to give the web browser a name and I'm going to call it my web browser.
Now, the web browser, I'm going to call it here or actually modify it here.
What I want to do is I want to set the value of that browser and I want to set it with something.
And because you can see we need the dependency property and an object which is a value.
So how do I get that?
Where do I get that from?
Well, there are multiple, multiple things here.
So one of them is we need a dependency property, so let's create one.
Let's put it at the top here.
And again, I'm just going to copy and paste it.
I'm going to show you how it looks like and what it does.
So it's a read only dependency property called HTML property.
And we register it.
We register it with HTML.
As you can see, it needs a name, string name, HTML, then a property type, an owner type and property
metadata.
So that's something that we have touched on when working with dependency properties in the WPF chapter.
So here I just created with HTML, the type is it's a string.
What is the owner?
It's the main window.
So our class here and what kind of data is this or which data do I want to give to it?
And I give it the on HTML changed metadata.
So what does that mean?
Well, whenever we set the HTML property on HTML changed will be called.
And that's this method here that we'll be called.
So now what we can do is we can set the value of my browser with the following.
We can go ahead and say HTML property and set it with HTML.
In order to use HTML, we need to make a little work around here or have a little workaround.
Actually, I'm going to call it my HTML like that and I need to create a variable here.
Just going to be a string my http l which is just going to say blah, just a string which is with stupid
text in here, nothing special.
But then once it's done downloading we get the result into our HTML string.
I couldn't just say HTML here because this string is locally created and I cannot create it or it's
within the scope of our task here and I cannot create it outside.
So that's why I need to have this little workaround.
So now I can go ahead and say my HTML is HTML.
So this.
Variable here, which is in the scope of our my web browser that we set here.
That's why I can go ahead now and set it in here.
So within the scope of our await task.
Now, of course, we need to finish this line.
So that's the way you can set the value of a web browser.
All right.
It's a little workaround, but it works, so let's test it.
Let's execute our code.
That's pressed the button.
And there we are.
So we have plenty of script errors, but that's because we haven't said anything else up.
But as you can see here we are at Google now, so we can go to images, to Google Maps and so forth.
So now we have created our little browser, which simply brings us to Google.
All right, cool.
So as I said, I'm not going to go too deep into browsers and stuff and I didn't even want to go too
deep into those topics.
But that's just the way you have to set it up.
That's a little, uh, yeah, a little set up that you need to do.
So you need to have this method, you need to have this dependency property, and then you can go ahead
and set the value of your browser with the HTML property, which is our dependency property and some
HTML code, which is the HTML code we download from Google.
All right.
Just quickly, to summarize once again, what is the idea of using different threads?
Well, you have the main thread which handles the UI, and if you want to do something that's heavy,
so which takes a little while to do, for example, downloading from the web, for example, copying
something from one file to another or working with hard drives or whatever.
That's where it really makes sense to do that in the background.
So you create a different task or a different thread which takes care of that.
So here we created a asynchronous task which does that in the background, and once that is done, we
can go ahead with the rest.
So it's not going to freeze our main thread, our UI is still going to work properly, and that's what
it's all about.
All right.
So see you in the.