SyncLock Required?


J

Jay

Given the following code I am wondering if SyncLock is required. Because I
am using system.timer is there already this type of lock behaviour in place?
I need to assure that I'm only selecting one distinct record at a time per
thread...

Public Class Form1

Private MessageArray() As MessageHandler
Private MH As MessageHandler

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

MH = New MessageHandler

Dim i As Integer
Dim iTo As Integer = 4 '4 threads
Dim iFrom As Integer = 1

ReDim MessageArray(iTo - iFrom)
Dim Msg As MessageHandler
For i = iFrom To iTo
Msg = New MessageHandler()
MessageArray(i - iFrom) = Msg
'pass parameters to the new thread
Msg.i = i
Msg.MainForm = Me
Dim ts As ThreadStart
ts = New ThreadStart(AddressOf Msg.ProcessingOutboundThread)
Dim wrkThread As Thread
wrkThread = New Thread(ts)
Msg.CurrentThread = wrkThread
wrkThread.SetApartmentState(ApartmentState.STA)
wrkThread.Name = i.ToString() 'for easier tracing
wrkThread.Start()
Next
'end start
End Sub

End Class

Class MessageHandler

Public MainForm As Form1
Public i As Integer
Public CurrentThread As Thread
Public iThreadId As Integer
Public cnString As String =
"server=servername;database=dbname;uid=username;pwd=password"
Private WithEvents Timer1 As System.Timers.Timer

Private Sub Timer1_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed

iThreadId = Thread.CurrentThread.GetHashCode()

Dim cn As SqlConnection
cn = New SqlConnection(cnString)
Dim cmd As SqlCommand
Dim dtr As SqlDataReader

Try
Try
cmd = New SqlCommand("select top 1 * from queue_table where
time_to_send=1", cn)
cn.Open()
dtr = cmd.ExecuteReader()
If dtr.HasRows() = True Then
dtr.Read()
Dim varE As String = dtr("employeetosendto")
Dim varM As String = dtr("employeemessageaddress")
dtr.Close()
cmd = New SqlCommand("update queue_table set
time_to_send=0 where employee='" & varE & "'", cn)
cmd.ExecuteNonQuery()
Call_Send_Message_Sub_Here 'call another sub pass employeemessageadress as
param
cmd = New SqlCommand("update queue_table set
sentmessage=1 where employee='" & varE & "'", cn)
cmd.ExecuteNonQuery()
end if
Catch ex As Exception
msgbox(ex.Message.ToString())
Finally
If cn.State = ConnectionState.Open Then cn.Close()
End Try
End If
Catch ex As Exception
msgbox(ex.Message.ToString())
Finally
If cn.State = ConnectionState.Open Then cn.Close()
End Try
End Sub

Public Sub ProcessingOutboundThread()
Dim iThreadId As Integer
iThreadId = Thread.CurrentThread.GetHashCode()

Timer1 = New System.Timers.Timer
Timer1.Interval = 5000 ' 5 seconds
Timer1.Start()

Application.Run()
End Sub
End Class

I'd appreciate any feedback on how I can make this a more threadsafe app or
more stable app. Thanks a lot.

Jay
 
Ad

Advertisements

B

Brian Gideon

Jay said:
Given the following code I am wondering if SyncLock is required. Because I
am using system.timer is there already this type of lock behaviour in place?
I need to assure that I'm only selecting one distinct record at a time per
thread...

Public Class Form1

Private MessageArray() As MessageHandler
Private MH As MessageHandler

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

MH = New MessageHandler

Dim i As Integer
Dim iTo As Integer = 4 '4 threads
Dim iFrom As Integer = 1

ReDim MessageArray(iTo - iFrom)
Dim Msg As MessageHandler
For i = iFrom To iTo
Msg = New MessageHandler()
MessageArray(i - iFrom) = Msg
'pass parameters to the new thread
Msg.i = i
Msg.MainForm = Me
Dim ts As ThreadStart
ts = New ThreadStart(AddressOf Msg.ProcessingOutboundThread)
Dim wrkThread As Thread
wrkThread = New Thread(ts)
Msg.CurrentThread = wrkThread
wrkThread.SetApartmentState(ApartmentState.STA)
wrkThread.Name = i.ToString() 'for easier tracing
wrkThread.Start()
Next
'end start
End Sub

End Class

Class MessageHandler

Public MainForm As Form1
Public i As Integer
Public CurrentThread As Thread
Public iThreadId As Integer
Public cnString As String =
"server=servername;database=dbname;uid=username;pwd=password"
Private WithEvents Timer1 As System.Timers.Timer

Private Sub Timer1_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed

iThreadId = Thread.CurrentThread.GetHashCode()

Dim cn As SqlConnection
cn = New SqlConnection(cnString)
Dim cmd As SqlCommand
Dim dtr As SqlDataReader

Try
Try
cmd = New SqlCommand("select top 1 * from queue_table where
time_to_send=1", cn)
cn.Open()
dtr = cmd.ExecuteReader()
If dtr.HasRows() = True Then
dtr.Read()
Dim varE As String = dtr("employeetosendto")
Dim varM As String = dtr("employeemessageaddress")
dtr.Close()
cmd = New SqlCommand("update queue_table set
time_to_send=0 where employee='" & varE & "'", cn)
cmd.ExecuteNonQuery()
Call_Send_Message_Sub_Here 'call another sub pass employeemessageadress as
param
cmd = New SqlCommand("update queue_table set
sentmessage=1 where employee='" & varE & "'", cn)
cmd.ExecuteNonQuery()
end if
Catch ex As Exception
msgbox(ex.Message.ToString())
Finally
If cn.State = ConnectionState.Open Then cn.Close()
End Try
End If
Catch ex As Exception
msgbox(ex.Message.ToString())
Finally
If cn.State = ConnectionState.Open Then cn.Close()
End Try
End Sub

Public Sub ProcessingOutboundThread()
Dim iThreadId As Integer
iThreadId = Thread.CurrentThread.GetHashCode()

Timer1 = New System.Timers.Timer
Timer1.Interval = 5000 ' 5 seconds
Timer1.Start()

Application.Run()
End Sub
End Class

I'd appreciate any feedback on how I can make this a more threadsafe app or
more stable app. Thanks a lot.

Jay

Jay,

The Elapsed event on System.Timers.Timer will run on a thread from the
ThreadPool if SynchronizingObject is null. When SynchronizingObject is
set to a Form or Control then the Timer will automatically marshal the
Elapsed event onto the thread hosting that Form or Control. In your
case the Elapsed event is running on another thread because you aren't
setting the SynchronizingObject property.

The thread running ProcessingOutboundThread isn't doing much. In fact,
the only thing it's doing is getting a Timer started. After that it
just blocks on Application.Run consuming system resources. You can
just as easily get the Timer started on the main UI thread inside the
Form_Load event.

Better yet, set the SynchronizingObject property to Form1 and the
Elapsed event will always run on the main UI thread. That will
absolutely guarentee that the queries will be executed one at a time.
And of course, since there wouldn't be more than one thread in play the
issue of thread-safety is moot.

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top