If you haven't looked at part 1 of this series, you might want to go back and check it out first. Also, all code here is based on VB.NET 2008 Express, to be certain that you can use totally free software.
In Part 1 of this series, the Timer component in the System.Windows.Forms namespace was used to smoothly vary the opacity of a Label component. The problem with that is that it's the wrong Timer. It happens to work ... this time ... but Microsoft doesn't recommend it and it might not work in a more complex application. A better Timer for WPF can be found in a different namespace, System.Timers. To change it, let's try simply changing the object created in the code as follows ...
Friend WithEvents myTimer As New System.Timers.Timer
Making this change creates a syntax error because this new object has different methods. In particular, it doesn't raise a Tick event. You can fix this pretty easily by changing the Handles clause to ...
Handles myTimer.Elapsed
But when you run the code, you get a runtime error that you might not have seen before:
The calling thread cannot access this object because a different thread owns it.
The error is thrown on this statement:
Label1.Opacity += 0.01
Welcome to the confusing world of multithreading!
A "thread" is a part of your program that can run independently. Think of multiple threads as being little sub-programs that are all running at the same time. The reason multithreading is a good idea is that your computer is so much faster than anything else, such as displaying information on the screen, that it makes a big difference in performance if one thread does one thing (such as painting the "UI" - user interface) while another one is working on something else.
Although multithreading makes the system perform a lot better, it makes the programmer's job harder. Because the threads are independent, one thread can't work with another one (like traditional subprograms do) because neither thread "knows" what the other one is doing.
In this case, the Timer in System.Timers works on one thread while the WPF UI - which is painting the image on the screen - works on another one. So when Timer wants to update the image on the screen (Label1.Opacity += 0.01), the CLR (Common Language Runtime - the part of .NET that actually executes the program) says, "No! Only the WPF UI thread can do that."
Sooner or later, the threads do have to work together. It is, after all, still the same system. It would be a really bad idea if the Timer could never update Label1.Opacity, for example. But you have to use extra code to make that work.
Updating the WPF UI isn't the only time you will use multithreading. It's been a part of .NET from the beginning and it's very useful in things like communication (waiting for a remote server to send something back) and databases (waiting for a query to return data). But, because WPF has caused situations like the Timer error to pop up in even very simple code, it's become something that even beginning programmers need to know about.
On the next page, Dispatcher, the object that lets you bridge different threads, is used to solve the problem with Timer.

