To Do: Compare to
Java
Multithreading is accomplished by using a combination of classes Thread and Monitor.
|
State |
|
|
Unstarted |
Thread created but not started. The class.method is the ThreadStart delegate the method to execute when the thread enters the Start state. Note that the method must not take any arguments. Dim myThread as New Thread(Address of class.method) |
|
Started |
Thread put in start state by calling start. myThread.Start() But the thread may not start executing immediately. It will start when it comes to top of priority queue and is allocated a timeslice (quantum) on the CPU As the program executes it can be placed back into the Started state by a number of different actions |
|
Running |
The thread as been dispatched to the cpu for execution and is executing. On first execution the thread executes the ThreadStart delegate passed to it The thread will remain in the Running state until its timeslice is up or it is moved to a different state by other actions. |
|
WaitSleepJoin |
A Running thread can enter the WaitSleepJoin state in 3 ways. The WaitSleepJoin state basically represents the combination of 3 different States, but they all result in the thread suspended for something else to happen. The thread can be put in this State in a a) Wait state, b) Sleep state, or c) Join state The 3 different events that can occur to put the Thread in
the WaitSleepJoin state are:
The program can call the Monitor.Wait() method. The thread stays in the WaitSleepJoin state until another thread(process) calls Monitor.pulse() or Monitor.PulseAll. Monitor.Pulse() moves the next waiting thread to the Started state. Monitor.PulseAll() moves all waiting threads to the Started state.
|
|
Suspended |
A thread in the Running state can be put in the Suspended state when the thread.Suspend() method is called. The thread can be moved back to the Started state when the thread.Resume() method is called. |
|
Stopped |
The thread enters the Stopped state when the ThreadStart delegate terminates. This can come about through normal execution or the thread can be forced to that state by either the program calling the Thread.Abort() method or some external process that has a handle on the Thread calls the abort method Garbage collection only takes place when the thread is in the stopped state and there are no references to the thread object |
|
Blocked |
A Running thread is moved to the Blocked state when a program issues an I/O request. The thread remains in the Blocked state until the I/O request is satisfied. The thread is then placed back to the Started state. Threads can also enter the Blocked state when another thread has acquired exclusive use on a data object (via Monitor.Enter()_ |
Thread Priorities
Threads can be assigned one of the following 5 priorities
ThreadPriority.Lowest
ThreadPriority.BelowNormal
ThreadPriority.Normal (default)
ThreadPriority.AboveNormal
ThreadPriority.Highest
The values are from Namspace System.Threading
Thread and Data Synchronization
Where program data needs to be manipulated by more that 1 thread, class Monitor can be used to synchronize access to the data.
A program needing exclusive access to an object, the Monitor.Enter() method is used to gain a lock on the data object.
Each object contains a SyncBlock that maintains the state of the objects lock. Monitor methods use the data in the SyncBlock to determine the state of the lock on the object.
Once an object is locked, all other threads accessing the object are put in the Blocked state until the object is unlocked.
The program gives up exclusive access by executing Monitor.Exit() on the data object. The Exit() method updates the SyncBlock status. Any threads that were placed in Blocked status waiting for the object can be set to the Started state.
Another way of obtaining a lock on an object is via the keyword SyncLock
SyncLock (objectToLock)
put in code that manipulates the objectToLock
End SyncLock
When the SyncLock block ends for any reason (normal execution, thrown exception, ) the lock is automatically released on objectToLock.
The objectToLock is the same object reference that would normally be passed to Montir.Enter(), Exit(), Pulse(), and PulseAll(). Oftentimes the objectToLock is Me.
Thread Methods
|
Get the thread executing the program |
Imports System.Threading
Dim myThread as Thread = Thread.CurrentThread note that you have access to Thread methods same as any other class |
|
Put yourself to sleep |
... sleep between 0 and 10 secs myThread.Sleep(randomObject.Next(10001) |
|
Starting a object method on a separate thread |
Imports System.Threading
create instance like any other Dim separateThreadObject as New MyObject()
create a thread and give it address of method to start execution on Dim separateThread as New Thread(AddressOf separateThreadObject.someMethod) add start the thread (actually just puts thread in start state ) separateThread.Start()
|
|
|
|
Objects requiring
synchronization
In general when object that requires synchronization is separate from the objects that manipulate it. The object contains set and get methods that contain calls to Monitor methods that to allow the data synchronization to occur. An object template for an object with synchronization is below.
Note that if an exception occurs after the Monitor.Enter() method is called, make sure to call Monitor.Exit() to release the lock. So it is a good idea to use Try/Catch/Finally and put the Monitor.Exit() call in the Finally block to ensure any locks are released.
|
Imports System.Threading Public Class ObjectWithSynchronziation Private data to be synchronized Public Property SomeProperty() as Integer Or string or . Get Try Monitor.Enter(Me) get a lock, if another process has lock you will Blocked If . Then Even if can continue, if data not available, go to a Blocked state Monitor.Wait(Me) End If when here you have the lock and data is available. do whatever you need to do
Catch anyExceptions as
Finally tell any waiting threads your are done (but you still have lock on object) Monitor.Pulse(Me) You may want to make a copy of the data so you wont have to worry about it being overlaid if objects Started from Pulse above immediately execute on this object Dim valueToReturn as Integer = valueToReturnFromAbove Now unlock the object Monitor.exit(Me) End Try And return the value Return valueToReturn End Get Set(ByVal integervalue as Integer) Try lock the object (or go into Blocked state if some other process has it locked) Monitor.Enter(Me) Check to make sure the object is in a state that you can change, if not go into a WaitSleepJoin state If Then Monitor.Wait(Me) End If You are here when you are good to go. Do your thing
Catch anyExceptions as
Finally Tell any waiting threads to wake up Monitor.Pulse(Me) And release the lock Monitor.Exit(Me) End Try End Set End Property End Class |
|
The advantage of a lock obtained via a SyncLock is that the lock is released if an exception occurs so no special exception coding is needed. Imports System.Threading Public Class ObjectWithSynchronziation Private data to be synchronized Public Property SomeProperty() as Integer Or string or . Get SyncLock(Me) get a lock, if another process has lock you will Blocked If . Then Even if can continue, if data not available, go to a Blocked state Monitor.Wait(Me) End If when here you have the lock and data is available. do whatever you need to do
tell any waiting threads your are done (but you still have lock on object) Monitor.Pulse(Me) And return the value note still w/in SyncLock Return valueToReturn End SyncLock since above Return exited block Synclock automatically released End Get Set(ByVal integervalue as Integer) SyncLock(Me) Check to make sure the object is in a state that you can change, if not go into a WaitSleepJoin state If Then Monitor.Wait(Me) End If You are here when you are good to go. Do your thing
Monitor.Pulse(Me) End Synclock End Set End Property End Class |
|
|