I have an interesting problem with a sort of producer-consumer system
for error logging. Consider the following code:
<code>
SyncLock _eventList.Sync Root
Dim item As ExceptionLogEnt ry
' If there are items, get the top one
If _eventList.Coun t > 0 Then
' Get the item from the queue
item = CType(_eventLis t.Dequeue, _
ExceptionLogEnt ry)
' If we got an item to log, log it
If Not item Is Nothing Then
WriteToLog(Buil dExceptionRepor t(item))
End If
End If
End SyncLock
</code>
This method is running as a new thread, created thus:
<code>
_thread = New Thread(AddressO f StartWatching)
_thread.Start()
</code>
FACTS:
1) The _thread is System.Threadin g.Thread, the _eventList is
System.Collecti ons.Queue, both are member variables of the class.
2) The class this code appears in could have more than one instances
(hence using threading).
3) I'm using .NET 1.1.
4) The _eventList object is referenced by the producer class (not
listed here), where Enqueue is called inside a SyncLock block.
MY PROBLEM:
Thing is, it seems that "_eventList.cou nt > 0" returns true, and still
is just before the dequeue call, but after the dequeue call it goes to
0, and "item" is NOTHING!!
I have no idea why this could be. Can anyone help!?!
Cheers,
<Shipcreak />
Full class follows:
Imports System.Text
Imports System.Threadin g
Public MustInherit Class LoggerBase
Private _name As String
Private _eventList As Queue
Private _thread As Thread
Private _stopRequested As Boolean
Public Sub New(ByVal pName As String)
_name = pName
End Sub
Public Sub AssignEventList (ByVal eventList As Queue)
If Not _eventList Is Nothing Then
SyncLock _eventList
_eventList = eventList
End SyncLock
Else
_eventList = eventList
End If
End Sub
Public Sub Start()
_stopRequested = False
_thread = New Thread(AddressO f StartWatching)
If Not _name Is Nothing AndAlso _name.Length > 0 Then
_thread.Name = _name
Else
_thread.Name = "Event Logging Thread"
End If
_thread.Start()
End Sub
Public Sub RequestStop()
_stopRequested = True
End Sub
Private Sub StartWatching()
While Not _stopRequested
' Lock the list
SyncLock _eventList.Sync Root
Dim item As ExceptionLogEnt ry
' If there are items, get the top one
If _eventList.Coun t > 0 Then
' Get the item from the queue
item = CType(_eventLis t.Dequeue, ExceptionLogEnt ry)
' If we got an item to log, log it
If Not item Is Nothing Then
WriteToLog(Buil dExceptionRepor t(item))
End If
End If
End SyncLock
' Wait for 1 sec to allow other threads to take their turn
Thread.CurrentT hread.Sleep(100 )
End While
End Sub
Private Function BuildExceptionR eport( _
ByVal ex As ExceptionLogEnt ry) As String
Dim ret As New StringBuilder
Dim e As ExceptionLogEnt ry = ex
If Not e Is Nothing Then
ret.AppendForma t("OS: {0}" & vbCrLf, ex.OSInfo)
ret.AppendForma t("Processor usage: {0}" & vbCrLf, _
ex.ProcessorUsa ge)
ret.AppendForma t("Working Set: {0}" & vbCrLf, _
ex.WorkingSet)
ret.AppendForma t("Free Memory: {0}" & vbCrLf, _
ex.FreeMemory)
ret.AppendForma t("OS UserName: {0}" & vbCrLf, _
ex.OSUserName)
ret.AppendForma t("Machine Name: {0}" & vbCrLf, _
ex.MachineName)
'ret.AppendForm at("Total HDD: {0}" & vbCrLf, _
ex.HDDTotal)
'ret.AppendForm at("Free HDD: {0}" & vbCrLf, _
ex.FreeHDD)
ret.AppendForma t("Occurred At: {0}" & vbCrLf, _
ex.Occurred)
ret.Append("Exc eption details:" & vbCrLf)
AppendException Details(ex.Caus ingException, ret)
WriteToLog(ret. ToString)
Else
WriteToLog("No exception data provided")
End If
End Function
Private Sub AppendException Details(ByVal ex As Exception, _
ByVal report As StringBuilder)
Dim e As Exception = e
Do While Not e Is Nothing
report.AppendFo rmat(" Message: {0}" & vbCrLf, _
e.Message)
report.AppendFo rmat(" Source: {0}" & vbCrLf, _
e.Source)
report.AppendFo rmat(" Method: {0}" & vbCrLf, _
e.TargetSite.Na me)
report.AppendFo rmat(" Help Link: {0}" & vbCrLf, _
e.HelpLink)
report.AppendFo rmat(" Stack Trace: {0}" & vbCrLf, _
e.StackTrace)
report.Append("------------------" & vbCrLf)
e = e.InnerExceptio n
Loop
End Sub
Protected MustOverride Sub WriteToLog(ByVa l item As String)
Protected MustOverride Sub WriteToLog(ByVa l item As String, _
ByVal type As EventLogEntryTy pe)
End Class
for error logging. Consider the following code:
<code>
SyncLock _eventList.Sync Root
Dim item As ExceptionLogEnt ry
' If there are items, get the top one
If _eventList.Coun t > 0 Then
' Get the item from the queue
item = CType(_eventLis t.Dequeue, _
ExceptionLogEnt ry)
' If we got an item to log, log it
If Not item Is Nothing Then
WriteToLog(Buil dExceptionRepor t(item))
End If
End If
End SyncLock
</code>
This method is running as a new thread, created thus:
<code>
_thread = New Thread(AddressO f StartWatching)
_thread.Start()
</code>
FACTS:
1) The _thread is System.Threadin g.Thread, the _eventList is
System.Collecti ons.Queue, both are member variables of the class.
2) The class this code appears in could have more than one instances
(hence using threading).
3) I'm using .NET 1.1.
4) The _eventList object is referenced by the producer class (not
listed here), where Enqueue is called inside a SyncLock block.
MY PROBLEM:
Thing is, it seems that "_eventList.cou nt > 0" returns true, and still
is just before the dequeue call, but after the dequeue call it goes to
0, and "item" is NOTHING!!
I have no idea why this could be. Can anyone help!?!
Cheers,
<Shipcreak />
Full class follows:
Imports System.Text
Imports System.Threadin g
Public MustInherit Class LoggerBase
Private _name As String
Private _eventList As Queue
Private _thread As Thread
Private _stopRequested As Boolean
Public Sub New(ByVal pName As String)
_name = pName
End Sub
Public Sub AssignEventList (ByVal eventList As Queue)
If Not _eventList Is Nothing Then
SyncLock _eventList
_eventList = eventList
End SyncLock
Else
_eventList = eventList
End If
End Sub
Public Sub Start()
_stopRequested = False
_thread = New Thread(AddressO f StartWatching)
If Not _name Is Nothing AndAlso _name.Length > 0 Then
_thread.Name = _name
Else
_thread.Name = "Event Logging Thread"
End If
_thread.Start()
End Sub
Public Sub RequestStop()
_stopRequested = True
End Sub
Private Sub StartWatching()
While Not _stopRequested
' Lock the list
SyncLock _eventList.Sync Root
Dim item As ExceptionLogEnt ry
' If there are items, get the top one
If _eventList.Coun t > 0 Then
' Get the item from the queue
item = CType(_eventLis t.Dequeue, ExceptionLogEnt ry)
' If we got an item to log, log it
If Not item Is Nothing Then
WriteToLog(Buil dExceptionRepor t(item))
End If
End If
End SyncLock
' Wait for 1 sec to allow other threads to take their turn
Thread.CurrentT hread.Sleep(100 )
End While
End Sub
Private Function BuildExceptionR eport( _
ByVal ex As ExceptionLogEnt ry) As String
Dim ret As New StringBuilder
Dim e As ExceptionLogEnt ry = ex
If Not e Is Nothing Then
ret.AppendForma t("OS: {0}" & vbCrLf, ex.OSInfo)
ret.AppendForma t("Processor usage: {0}" & vbCrLf, _
ex.ProcessorUsa ge)
ret.AppendForma t("Working Set: {0}" & vbCrLf, _
ex.WorkingSet)
ret.AppendForma t("Free Memory: {0}" & vbCrLf, _
ex.FreeMemory)
ret.AppendForma t("OS UserName: {0}" & vbCrLf, _
ex.OSUserName)
ret.AppendForma t("Machine Name: {0}" & vbCrLf, _
ex.MachineName)
'ret.AppendForm at("Total HDD: {0}" & vbCrLf, _
ex.HDDTotal)
'ret.AppendForm at("Free HDD: {0}" & vbCrLf, _
ex.FreeHDD)
ret.AppendForma t("Occurred At: {0}" & vbCrLf, _
ex.Occurred)
ret.Append("Exc eption details:" & vbCrLf)
AppendException Details(ex.Caus ingException, ret)
WriteToLog(ret. ToString)
Else
WriteToLog("No exception data provided")
End If
End Function
Private Sub AppendException Details(ByVal ex As Exception, _
ByVal report As StringBuilder)
Dim e As Exception = e
Do While Not e Is Nothing
report.AppendFo rmat(" Message: {0}" & vbCrLf, _
e.Message)
report.AppendFo rmat(" Source: {0}" & vbCrLf, _
e.Source)
report.AppendFo rmat(" Method: {0}" & vbCrLf, _
e.TargetSite.Na me)
report.AppendFo rmat(" Help Link: {0}" & vbCrLf, _
e.HelpLink)
report.AppendFo rmat(" Stack Trace: {0}" & vbCrLf, _
e.StackTrace)
report.Append("------------------" & vbCrLf)
e = e.InnerExceptio n
Loop
End Sub
Protected MustOverride Sub WriteToLog(ByVa l item As String)
Protected MustOverride Sub WriteToLog(ByVa l item As String, _
ByVal type As EventLogEntryTy pe)
End Class
Comment