GarboSzondi
Members-
Content Count
1 -
Joined
-
Last visited
About GarboSzondi
-
Rank
Newbie
-
Threading Example A simple introduction to threading in C#
GarboSzondi posted a topic in Programming
Threading Example This example assumes you have Visual Studio 2005 or greater and are somewhat familiar with its use. Threading is an extremely useful method of making your programs more efficient. Threading allows your program to multitask. Multitasking is something we all do everyday. When you wake up in the morning you might start a pot of coffee. Then while that's brewing you start some eggs for breakfast. While they are cooking and the coffee is still brewing, you might go outside and get the paper, which you will read between bites of breakfast and sips of coffee. That's just one simple example, but suppose you stood there waiting for the coffee to brew before you started breakfast. Then you waited for the eggs to cook before going out to get the paper. Then you ate breakfast before reading the paper. You would probably be late for work. You can, and often do, do many things at the same time, and so can your computer – using threads. Each thread is a separate process, similar to the processes discussed above: making coffee, making breakfast, getting the paper, reading the paper and eating breakfast. The best way to illustrate the use of threads is using an example. This is where I would normally have to create an example program, give you the code and ask you to follow my instructions on how to add a thread. Fortunately, however, Microsoft has provided a great example program with Visual Studio 2005. I think it is included with 2008 and 2010 also, but I don't have either in front of me to check. All you need to do to get started is: Open Visual Studio 2005 Go to File | New Project Select “Starter Kits” under the Visual C# tree Select “Screen Save Starter Kit” Optionally give it a name Then click “OK” It creates a Windows screen saver and provides an HTML page telling you how to use it, deploy it and even suggestions on extending the screen saver. One suggestion which they don't include is to add a thread. This is what we are going to do. First, familiarize yourself with the screen saver by reading the documentation, particularly the section “Accessing the Options Dialog Box”. Follow the instructions on “Accessing the Options Dialog Box” and point it to a folder of images to display. Start with a folder with only a few images and run the screen saver from Visual Studio using F5. It should start pretty quickly and display your images instead of the ones it displayed the first time you ran it. Now load your image folder up with a bunch of images, preferably with pretty high resolution, and run it again. Notice it now takes much longer for the screen saver to display. The reason for this is in the method “LoadImagesFromFolder”. It goes through every image file in your folder and tries to load it, which is exactly what you want it to do. The only problem is that your program waits for it to finish before it can proceed. This is where a thread comes in handy. Threading can be a very tricky task when done from scratch. You have to make sure that your process begins when the resources required for it are ready, ends gracefully and doesn't crash into other processes. Visual Studio makes threading easy with a component called “BackgroundWorker”. You still have to make sure that the resources it requres are available, but you are spared the complexities of spawning a separate process. It's under “Components” in your toolbox. Drag one of those onto your screensaver form in design mode. Now go to the “Properties” of your backgroundWorker1 and click on the lightning button (events). It has only 3 events. We will only concern ourselves with one of them at this point, “DoWork”. Double click on the space to the right of “DoWork” in the even viewer and Visual Studio will create an event for you called “backgroundWorker1_DoWork”. We're going to move the work of getting all of the images from your folder into this thread. Do a search for “ LoadImagesFromFolder();” to find where it is called. Highlight this line of code and cut it from the code using Ctrl+x. Now in its place type in “backgroundWorker1.RunWorkerAsync();” Now go back down to your bacgroundWorker1_DoWork event and paste the code you just cut into the body of the event so it looks like this: private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { LoadImagesFromFolder(); } The LoadBackgroundImage method which now contains your call to the background worker should look like this: private void LoadBackgroundImage() { // Initialize the background images. backgroundImages = new List<Image>(); currentImageIndex = 0; if (Directory.Exists(Properties.Settings.Default.BackgroundImagePath)) { try { // Try to load the images given by the users. backgroundWorker1.RunWorkerAsync(); } catch { // If this fails, load the default images. LoadDefaultBackgroundImages(); } } // If no images were loaded, load the defaults if (backgroundImages.Count == 0) { LoadDefaultBackgroundImages(); } } Go ahead and run the program again using F5. Notice that it starts very quickly but begins by loading the default images. When the thread you created using the BackgroundWorker has finished it begins to display the images loaded from your folder. This is a very good example of how using a thread can make your program more efficient and user friendly. Rather than waiting a long time for all the images to load before seeing the screensaver, the user only has to wait a split-second for the images included in the program resources to load and then, after the images have finished loading, it displays the ones stored in a folder. If you really want to get fancy you might try a thread for each image it tries to load. This would be much more efficient, since it would allow us to load up the lower resolution images right away without having to wait for the high resolution images to load. This is a bit trickier, however, since we need to create a BackgroundWorker for each image and add it to the image list when it is loaded.