We have another useful class in .net- Monitor.
The Monitor class provides functions through which we can implement locking
mechanism in the threads. In general it works similar to the SyncLock but the
advantage is that we can do lock based error handling with Monitor. For this we
can use Enter() and Exit()
functions with our usual error handling Try…Catch…Finally
block. Let's modify the DoAction method to use Monitor as given in the class
below.
To understand its implementation, just modify the existing
DoAction method to use Monitor class as given below. No need to make any change
in Main() for now.
Listing 9 – Thread delegate method using Monitor
class
Public Class CThread
Public Sub DoAction()
Try
Threading.Monitor.Enter(Me)
Console.WriteLine("{0} : {1} : To sleep now...", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
Threading.Thread.Sleep(5000)
Console.WriteLine("{0} : {1} : is woke up...", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
Catch ex As Exception
Console.WriteLine("{0} : {1} : Error in monitor section,exiting monitor...", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
' do some job like error logging in file or database..
Finally
Threading.Monitor.Exit(Me)
End Try
End Sub
End Class
We can code Monitor.Enter and Monitor.Exit methods anywhere
inside the Try…Catch…Finally block of the delegate method. In this way it gives
more flexibility to implement and handle complex logic inside lock area.
Run the application (CTRL+F5), you would see console window
as:
Figure 4 – Console output window of Monitor
implementation
As this result same as the SyncLock example we had done
before. To test how Monitor is useful with Try…Catch…Finally block, we will
modify the DoAction method to read a file (say c:\abc.txt)
which does not exist in the computer. The very first instance of the delegate method
will be the victim of FileNotFound error. In catch block we will create that
file so that next all other threads will not get that error. Here is complete
code of class containing DoAction method.
Listing 10 – Thread delegate method using Monitor
class and Try…Catch…Finally to handle runtime errors.
Public Class CThread
Public Sub DoAction()
Try
Threading.Monitor.Enter(Me)
Console.WriteLine("{0} : {1} : To sleep now...", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
Threading.Thread.Sleep(5000)
IO.File.ReadAllText("c:\abc.txt")
Console.WriteLine("{0} : {1} : is woke up...", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
Catch ioErr As IO.FileNotFoundException
Console.WriteLine("{0} : {1} : Error- File Not Found.", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString())
' create the file for next all threads
IO.File.Create("c:\abc.txt")
Catch ex As Exception
Console.WriteLine("{0} : {1} : Error in monitor section : {2}", _
Threading.Thread.CurrentThread.ManagedThreadId, Now.ToString(), ex.ToString())
' do some job like error logging in file or database..
Finally
Threading.Monitor.Exit(Me)
GC.Collect()
End Try
End Sub
End Class
One more thing you may have noticed that I have used GC.Collect()
at the end in finally block. I used it to release any resources (a file in this
example) being used by thread, so that other thread would not get any file
access error.
Run the application (CTRL+F5), you would see the console
output window as:
Figure 5 – Console output of the application
showing error handling with Monitor uses.
You can see in the result that managed thread # 3 got a
FileNotFound error and next thread # 4 executed normally since thread # 3
created the missing file in the Catch block.
Few sample project of this article can be downloaded though
the download links given below.