Hello everyone! I have a couple of questions about some threading best practices. Here is some of the code I have written that spawns some threadpool threads and each threadpool thread opens a log file on processes it (still dont know if its any faster than a single thread at this point) >
Here is the code in the CustomSql library >Code:Imports System.IO Imports System.Data.SqlClient Imports System.Threading Public Class Form1 Dim SqlDataConn As New SqlClient.SqlConnection(My.Settings.SqlDataConn) Dim CustomSql As New SqlDataRetrieve.SqlReadOrChange Dim LogsScanned, MaxThreads, PlaceHolder, AvailableThreads As Integer Dim TempLogsDir As String = "TempLogs" Dim SqlLock As New Object Private Sub ButtonReadLogs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonReadLogs.Click WriteToLogFile(Now.ToString() + " -Process started") SqlDataConn.Open() My.Computer.FileSystem.CreateDirectory(TempLogsDir) For Each LogFile As String In My.Computer.FileSystem.GetFiles(Me.TextBoxLogPath.Text, FileIO.SearchOption.SearchTopLevelOnly) Dim LogFileInfo As New FileInfo(LogFile) If Not My.Computer.FileSystem.FileExists(TempLogsDir + "\" + LogFileInfo.Name) Then My.Computer.FileSystem.CopyFile(LogFile, TempLogsDir + "\" + LogFileInfo.Name) End If LogFile = Nothing LogFileInfo = Nothing Next LogFile For Each CopiedLogFile In My.Computer.FileSystem.GetFiles(TempLogsDir) ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ReadLogFile), CopiedLogFile) LogsScanned += 1 CopiedLogFile = Nothing Next CopiedLogFile ThreadPool.GetMaxThreads(MaxThreads, PlaceHolder) ThreadPool.GetAvailableThreads(AvailableThreads, PlaceHolder) Do While MaxThreads <> AvailableThreads ThreadPool.GetMaxThreads(MaxThreads, PlaceHolder) ThreadPool.GetAvailableThreads(AvailableThreads, PlaceHolder) Thread.Sleep(5000) Loop WriteToLogFile(Now.ToString() + " -Process Finished") MessageBox.Show("Finished!") End Sub Private Sub ReadLogFile(ByVal state As Object) Dim LogFilePath As String = DirectCast(state, String) Dim MyCommand As New SqlCommand Dim oRead As System.IO.StreamReader Try oRead = File.OpenText(LogFilePath) While oRead.Peek <> -1 Try Dim LogFileLine As String = oRead.ReadLine.Replace("'", "`") If Not LogFileLine.StartsWith("#") Then If Not LogFileLine.Contains("EVJournaling") Then LogFileLine = LogFileLine.Replace(",", "','") LogFileLine = LogFileLine.Insert(0, "'") LogFileLine = LogFileLine + "'" MyCommand.CommandText = ("sp_InsertMailEvent " + LogFileLine) SyncLock SqlLock CustomSql.InsertUpdateDelete(SqlDataConn, MyCommand) End SyncLock LogFileLine = String.Empty MyCommand.CommandText = String.Empty Else LogFileLine = String.Empty End If End If Catch ex As Exception End Try End While oRead.Close() oRead.Dispose() Catch ex As Exception End Try MyCommand.Dispose() LogFilePath = Nothing state = Nothing End Sub Private Sub WriteToLogFile(ByVal Text As String) File.AppendAllText("ExchangeServerMT_" & DateString & ".log", Text & ControlChars.CrLf) Text = Nothing End Sub End Class
My question is this; Is it necessary to use some sort of synchronizing (ie: im using SyncLock in the ReadLogFile sub) when making the insert call into the CustomSql class? If I dont use it, I get some strange NullException errors in the CustomSql class. I'm still a bit confused on WHEN I should use some sort of synchronizing when working with multi threading. Like when each threadpool thread gets called, does each one keep track of all its own variables in the ReadLogFile sub, so there is no contamination of values between the threads? I understand the simple use of synchronizing like this article multithreading, but would like some more help understanding using it in more complicated code. Thanks in advance for any help you can give me!Code:Imports System.Data.SqlClient Public NotInheritable Class SqlReadOrChange ''' <summary> ''' Connects to a SQL database, executes a SqlCommand, and returns the number of rows affected. ''' </summary> ''' <param name="MyConnection">The connection used to open the SQL Server database</param> ''' <param name="MyCommand">The SqlCommand to run against the connection</param> ''' <param name="KeepConnectionOpen">Determines whether or not to keep the connection to the database open. Default is True.</param> ''' <remarks></remarks> Public Function InsertUpdateDelete(ByRef MyConnection As SqlConnection, ByVal MyCommand As SqlCommand, Optional ByVal KeepConnectionOpen As Boolean = True) As Integer Try MyCommand.Connection = MyConnection If MyConnection.State <> ConnectionState.Open Then MyConnection.Open() End If InsertUpdateDelete = MyCommand.ExecuteNonQuery() If KeepConnectionOpen = False Then If MyConnection.State <> ConnectionState.Closed Then MyConnection.Close() End If End If Catch ex As Exception InsertUpdateDelete = Nothing End Try MyCommand.Dispose() End Function End Class![]()




Reply With Quote