Hello,
I am using SyncLock to synchronize threads access to the returnedDataQueue object, the queue is public property, I know it's not a good practice to lock public variables but I don't know how to accomplish my goal without doing it.
I have 2 threads accessing the same queue, the first thread (ListenerThread) listens to TCP transactions that comes from the server, then it queues them into the returnedDataQueue, the second thread dequeues from the returnedDataQueue.
The Listener Thread:
------------
Public Class ConnectionHandler
Inherits TcpClient
Public Event dataArrived()
Private listenThread As Thread
Private _returnedDataQueue As Queue
Public Property returnedDataQueue() As Queue
Get
Return Queue.Synchronized(_returnedDataQueue)
End Get
Set(ByVal value As Queue)
_returnedDataQueue = value
End Set
End Property
Sub New(ByVal ip As String, ByVal port As Integer)
returnedDataQueue = New Queue
listenThread = New Thread(AddressOf listen)
listenThread.Name = "ListenThread"
listenThread.SetApartmentState(Threading.ApartmentState.STA)
listenThread.Start()
End Sub
Public Sub listen()
Dim networkStream As NetworkStream
Do While Not MyBase.Connected
Me.connect()
Loop
Dim strData As String
Do While MyBase.Connected
If networkStream.CanRead Then
Dim bytes(MyBase.ReceiveBufferSize) As Byte
networkStream.Read(bytes, 0, CInt(MyBase.ReceiveBufferSize))
strData = Encoding.ASCII.GetString(bytes).Trim
SyncLock returnedDataQueue.SyncRoot
returnedDataQueue.Enqueue(strData)
End SyncLock
RaiseEvent dataArrived()
End If
Loop
End Sub
End Class
In the main thread, I handle the dataArrived() events:
Dequeu Thread:
-------------
Public Class MyService
Inherits System.ServiceProcess.ServiceBase
Private WithEvents objConnectionHandler As ConnectionHandler
Private objUdpClient As UDPMulticaster
Protected Overrides Sub OnStart(ByVal args() As String)
objUdpClient = New UDPMulticaster(settings.MulticastIP, settings.MulticastPort, settings.MulticastPortEP)
objConnectionHandler = New ConnectionHandler(settings.IP, settings.Port)
End Sub
Private Sub objConnectionHandler_dataArrived() Handles objConnectionHandler.dataArrived
Try
SyncLock objConnectionHandler.returnedDataQueue.SyncRoot
While objConnectionHandler.returnedDataQueue.Count > 0
Dim strTemp As String = objConnectionHandler.returnedDataQueue.Dequeue
Dim success As Boolean = CBool(wcfService.ProcessTransaction(strTemp))
If success Then
Dim seq As Integer = CInt(wcfService.getSequenceNumber())
objUdpClient.multicastToNetwork(strTemp, seq)
End If
End While
End SyncLock
Catch ex As Exception
End Try
End Sub
End Class
Suddenly, the ListenThread stops working, I don't get any errors, it looks that the code is not executing anymore and the thread is waiting for something, after running the code for couple of days on a busy system, I believe the Dequeue Thread locks the returnedDataQueue for long time, then the listen thread won't be able to queue any new transactions!
Is there anything wrong with the code? is there any alternative approach to prevent the threads from accessing the queue simultaneously?
Thanks,
Sam