Free mag vol1 | Page 775

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING Printer p = new Printer(); Thread bgroundThread = new Thread(new ThreadStart(p.PrintNumbers)); } // This is now a background thread. bgroundThread.IsBackground = true; bgroundThread.Start(); Notice that this Main() method is not making a call to Console.ReadLine() to force the console to remain visible until you press the Enter key. Thus, when you run the application, it will shut down immediately because the Thread object has been configured as a background thread. Given that the Main() method triggers the creation of the primary foreground thread, as soon as the logic in Main() completes, the AppDomain unloads before the secondary thread is able to complete its work. However, if you comment out the line that sets the IsBackground property, you will find that each number prints to the console, as all foreground threads must finish their work before the AppDomain is unloaded from the hosting process. For the most part, configuring a thread to run as a background type can be helpful when the worker thread in question is performing a noncritical task that is no longer needed when the main task of the program is finished. For example, you could build an application that pings an e-mail server every few minutes for new e-mails, updates current weather conditions, or some other noncritical task. The Issue of Concurrency When you build multithreaded applications, your program needs to ensure that any piece of shared data is protected against the possibility of numerous threads changing its value. Given that all threads in an AppDomain have concurrent access to the shared data of the application, imagine what might happen if multiple threads were accessing the same point of data. As the thread scheduler will force threads to suspend their work at random, what if thread A is kicked out of the way before it has fully completed its work? Thread B is now reading unstable data. To illustrate the problem of concurrency, let’s build another Console Application project named MultiThreadedPrinting. This application will once again make use of the Printer class created previously, but this time the PrintNumbers() method will force the current thread to pause for a randomly generated amount of time. public class Printer { public void PrintNumbers() { ... for (int i = 0; i < 10; i++) { // Put thread to sleep for a random amount of time. Random r = new Random(); Thread.Sleep(1000 * r.Next(5)); Console.Write("{0}, ", i); } Console.WriteLine(); } } 720