Visual Basic 2005 for Programmers (2nd Edition)
15.4. Creating and Executing Threads
Figure 15.3 shows how to construct Thread objects and demonstrates class Thread's Shared method Sleep. The program creates three threads of execution, each with the default priority Normal. Each thread displays a message indicating that it is going to sleep for a random interval of from 0 to 5000 milliseconds, then goes to sleep. When each thread awakens, it displays its name, indicates that it is done sleeping, terminates and enters the Stopped state. You will see that method Main (i.e., the Main thread of execution) terminates before the application terminates. The program consists of method Main (lines 633), which creates the three threads, and class MessagePrinter (lines 3659), which defines a Print method containing the actions each thread will perform. Figure 15.3. Threads sleeping and printing.
Objects of class MessagePrinter control the life cycle of each of the three threads created in class THReadTester's Main method. Class MessagePrinter consists of instance variable sleepTime (line 37), Shared variable random (line 38), a constructor (lines 4144) and a Print method (lines 4758). Variable sleepTime stores a random integer value chosen when a new MessagePrinter object's constructor is called. Each thread controlled by a MessagePrinter object sleeps for the amount of time specified by the corresponding MessagePrinter object's sleepTime. The MessagePrinter constructor (lines 4144) initializes sleepTime to a random number of milliseconds from 0 up to, but not including, 5001 (i.e., from 0 to 5000). Method Print begins by obtaining a reference to the currently executing thread (line 49) via class THRead's Shared property CurrentThread. The currently executing thread is the one that invoked method Print. Next, lines 5253 display a message indicating the name of the currently executing thread and stating that the thread is going to sleep for a certain number of milliseconds. Note that line 52 uses the currently executing thread's Name property to obtain the thread's name (set in method Main when each thread is created). Line 54 invokes Shared Thread method Sleep to place the thread in the WaitSleepJoin state. At this point, the thread loses the processor, and the system allows another thread to execute if one is ready to run. When the thread awakens, it re-enters the Running state and waits to be assigned a processor by the thread scheduler. When the MessagePrinter object enters the Running state again, line 57 outputs the thread's name in a message indicating that the thread is done sleeping, and method Print terminates. Module ThreadTester's Main method (lines 633) creates three MessagePrinter objects (lines 9, 14 and 19). Lines 1011, 1516 and 2021 create and initialize three Thread objects. Each Thread's constructor receives as an argument a ThreadStart delegate. A THReadStart delegate represents a method with no arguments and no return value that specifies the actions a thread will perform. Lines 1011 initialize the ThreadStart delegate for tHRead1 with printer1's Print method. The AddressOf operator creates a delegate that references a specific methodin this case printer1.Print. When thread1 enters the Running state for the first time, thread1 will invoke printer1's Print method to perform the tasks specified in method Print's body. Thus, thread1 will print its name, display the amount of time for which it will go to sleep, sleep for that amount of time, wake up and display a message indicating that the thread is done sleeping. At that point, method Print will terminate. A thread completes its task when the method specified by its ThreadStart delegate terminates, at which point the thread enters the Stopped state. When thread2 and thread3 enter the Running state for the first time, they invoke the Print methods of printer2 and printer3, respectively. Threads thread2 and thread3 perform the same tasks as thread1 by executing the Print methods of the objects to which printer2 and printer3 refer (each of which has its own randomly chosen sleep time). Lines 12, 17 and 22 set each Thread's Name property, which we use for output purposes. Error-Prevention Tip 15.1
Lines 2830 invoke each Thread's Start method to place the threads in the Running state. Method Start returns immediately from each invocation, then line 32 outputs a message indicating that the threads were started, and the Main tHRead of execution terminates. The program itself does not terminate, however, because there are still non-background threads that are alive (i.e., the threads are Running and have not yet reached the Stopped state). The program will not terminate until its last non-background thread dies. When the system assigns a processor to a thread, the thread enters the Running state and calls the method specified by the thread's THReadStart delegate. In this program, each thread invokes method Print of the appropriate MessagePrinter object to perform the tasks discussed previously. Note that the sample outputs for this program show each thread and the thread's sleep time in milliseconds as the thread goes to sleep. The thread with the shortest sleep time normally awakens first, then indicates that it is done sleeping and terminates. In Section 15.8, we discuss multithreading issues that could prevent the thread with the shortest sleep time from awakening first. Notice in the second sample output that thread1 and thread2 were able to report their sleep times before Main could output its final message. This means that the main thread's quantum ended before it could finish executing Main, and thread1 and tHRead2 each got a chance to execute. |
Категории