Perform Multiple Tasks Using Threads
C# makes it easier to use threads in your programs. Learn to create, start, and manage multiple-thread execution
by Bill Wagner
Multithreading is one way to improve the perceived performance of your programs. A multithreaded program does not run faster than a single-threaded program, but because multithreaded programs do more than one operation at a time, the perception is that they are faster. Multithreaded programs are a large topic. In this article, I am going to focus on the C# mechanisms for creating, starting, and managing multiple-thread execution. C# uses the same techniques as previous languages for managing data concurrency. You can learn these techniques from any good multithreading text (see Resources).
When you start a new thread, it will execute a function, and then the thread will exit. That’s really all you need to do to execute code in a different thread. The rest of the code you write to manage threads involves getting data into the new thread, managing shared data access, and retrieving results from the new thread after it’s finished its work. Using object-oriented techniques in C# and .NET, you can manage multiple threads more easily than you ever have. To execute code in a new thread, you create a class that performs the work for you in another thread. You create properties to set the initial parameters. You create a delegate to start the thread. Finally, you create properties to retrieve the results.
Classes That Create Threads
I am going to modify the Mandelbrot program from an article in Visual Studio Magazine to illustrate these concepts (see Resources). The single-threaded version of the program stopped responding to user input when the user tried to zoom in to a particular portion of the set. I was unsatisfied with this for two reasons. First, if I was animating the set, all animation stopped until the zoom operation had finished. Second, if I had accidentally pressed the mouse button at the wrong location, I had to wait for the operation to finish, which took a few seconds. So, I decided to put the set generation code into a different thread.
Let’s go through the steps I outlined earlier to move the set generation into a second thread. The new thread should create a new copy of the Mandelbrot set points, in a different data structure. This new set of points is the output from the thread. The input/output parameters are the boundaries and scale for the set. To begin, simply make a new class to create a new image map, and add a property to retrieve the new set (see Listing 1). Although there is no thread code here yet, it does satisfy the interface requirements for the new class I listed. You construct the SetThreadMaker, giving it the necessary parameters to perform its functions. Then, it creates a new image map for you. Once the constructor has finished, you can retrieve the image map and use it to generate your images.
Back to top