Vb.net 使用写队列和多线程

Vb.net 使用写队列和多线程,vb.net,multithreading,Vb.net,Multithreading,我有一个进程运行在一个单独的线程中,该线程通过以太网读取数据,并为每次读取引发一个事件。然后,在类树上处理这些数据。在类树的顶部,我想将处理后的数据存储到SQL表中。这种读取速率可能相当快,有时甚至更快,但平均而言,它比我对SQL的写入速率要慢。这就是我想要排队的原因。我也希望我的窗口不冻结,所以我想要一个单独的线程 下面的代码可以工作,但我在多线程方面相当缺乏经验,这是一种完成任务的好方法吗 Private addLogQueue As New Queue Private dequeueing

我有一个进程运行在一个单独的线程中,该线程通过以太网读取数据,并为每次读取引发一个事件。然后,在类树上处理这些数据。在类树的顶部,我想将处理后的数据存储到SQL表中。这种读取速率可能相当快,有时甚至更快,但平均而言,它比我对SQL的写入速率要慢。这就是我想要排队的原因。我也希望我的窗口不冻结,所以我想要一个单独的线程

下面的代码可以工作,但我在多线程方面相当缺乏经验,这是一种完成任务的好方法吗

Private addLogQueue As New Queue
Private dequeueing As Boolean = False
Public Sub addLogHandler(ByVal machineName As String, ByVal LogTime As Date, ByVal EventLog As String, ByVal EventValue As String)
    addLogQueue.Enqueue("INSERT INTO ... some SQL CODE")
    Dim Thread1 As New System.Threading.Thread(AddressOf addLog)
    Thread1.Start
End Sub
Private Sub addLog()
    If Not dequeueing Then
        dequeueing = True
        While addLogQueue.Count <> 0
            Try
                SQLCon.Open()
                SQLCmd = New SqlCommand(addLogQueue.Dequeue(), SQLCon)
                SQLCmd.ExecuteNonQuery()
                SQLCon.Close()
            Catch ex As Exception
                MsgBox(ex.Message)
                If SQLCon.State = ConnectionState.Open Then
                    SQLCon.Close()
                End If
            End Try
        End While
        dequeueing = False
    End If
End Sub
Private addLogQueue作为新队列
作为布尔值的私有出列=False
公共子addLogHandler(ByVal machineName作为字符串,ByVal LogTime作为日期,ByVal EventLog作为字符串,ByVal EventValue作为字符串)
Enqueue(“插入…一些SQL代码”)
Dim Thread1作为新的System.Threading.Thread(addLog的地址)
1.开始
端接头
私有子addLog()
如果不排队,那么
出列=真
同时添加日志队列。计数0
尝试
SQLCon.Open()
SQLCmd=新的SqlCommand(addLogQueue.Dequeue(),SQLCon)
SQLCmd.ExecuteNonQuery()
SQLCon.Close()
特例
MsgBox(例如消息)
如果SQLCon.State=ConnectionState.Open,则
SQLCon.Close()
如果结束
结束尝试
结束时
退出队列=错误
如果结束
端接头

我建议您阅读以下文章:。此外,出于性能原因,您可能希望保持线程打开,数据库连接打开,只需使用等待事件确定是否应检查队列中的更多条目。请参阅本文:。保持连接打开实际上取决于消息到达的频率。非常频繁:保持连接打开,间歇性:使用后关闭

Dim Thread1 As New System.Threading.Thread(AddressOf addLog)
Private Shared mre As New ManualResetEvent(False)
Private addLogQueue As New Queue
Private shutDown as boolean = false

Public Sub Main   
    Thread1.Start    
End Sub
Public Sub addLogHandler(ByVal machineName As String, ByVal LogTime As Date, ByVal EventLog As String, ByVal EventValue As String)
    addLogQueue.Enqueue("INSERT INTO ... some SQL CODE")
    mre.Set()
End Sub

Private Sub addLog()
    dim cmdString as String
    Try
        Using SQLCon as New SQLConnection
            SQLCon.Open()
            While Not shutDown
                mre.WaitOne()
                mre.Reset()
                While addLogQueue.Count <> 0
                    cmdString = addLogQueue.Dequeue()
                    SQLCmd = New SqlCommand(cmdString, SQLCon)
                    SQLCmd.ExecuteNonQuery()
                End While
            End While
        End Using
    Catch ex As Exception
        My.Application.Log.WriteException(ex,TraceEventType.Error, cmdString)
    End Try
End Sub
Dim Thread1作为新的System.Threading.Thread(addLog的地址)
私有共享mre作为新ManualResetEvent(错误)
私有addLogQueue作为新队列
私有关闭为布尔值=false
公用支线
1.开始
端接头
公共子addLogHandler(ByVal machineName作为字符串,ByVal LogTime作为日期,ByVal EventLog作为字符串,ByVal EventValue作为字符串)
Enqueue(“插入…一些SQL代码”)
mre.Set()
端接头
私有子addLog()
将cmdString设置为字符串
尝试
使用SQLCon作为新的SQLConnection
SQLCon.Open()
而不是关机
韦通先生()
mre.Reset()
同时添加日志队列。计数0
cmdString=addLogQueue.Dequeue()
SQLCmd=新的SqlCommand(cmdString,SQLCon)
SQLCmd.ExecuteNonQuery()
结束时
结束时
终端使用
特例
My.Application.Log.WriteException(例如,TraceEventType.Error,cmdString)
结束尝试
端接头

此外,如果您希望程序执行无人值守的监视,您可能需要查找一些关于编写服务的文章,因为这类事情作为一项服务工作得更好。另外,您可以让一个线程接受命令字符串并将其添加到队列中,第二个线程将其写入数据库。

我想请您参阅以下文章:。此外,出于性能原因,您可能希望保持线程打开,数据库连接打开,只需使用等待事件确定是否应检查队列中的更多条目。请参阅本文:。保持连接打开实际上取决于消息到达的频率。非常频繁:保持连接打开,间歇性:使用后关闭

Dim Thread1 As New System.Threading.Thread(AddressOf addLog)
Private Shared mre As New ManualResetEvent(False)
Private addLogQueue As New Queue
Private shutDown as boolean = false

Public Sub Main   
    Thread1.Start    
End Sub
Public Sub addLogHandler(ByVal machineName As String, ByVal LogTime As Date, ByVal EventLog As String, ByVal EventValue As String)
    addLogQueue.Enqueue("INSERT INTO ... some SQL CODE")
    mre.Set()
End Sub

Private Sub addLog()
    dim cmdString as String
    Try
        Using SQLCon as New SQLConnection
            SQLCon.Open()
            While Not shutDown
                mre.WaitOne()
                mre.Reset()
                While addLogQueue.Count <> 0
                    cmdString = addLogQueue.Dequeue()
                    SQLCmd = New SqlCommand(cmdString, SQLCon)
                    SQLCmd.ExecuteNonQuery()
                End While
            End While
        End Using
    Catch ex As Exception
        My.Application.Log.WriteException(ex,TraceEventType.Error, cmdString)
    End Try
End Sub
Dim Thread1作为新的System.Threading.Thread(addLog的地址)
私有共享mre作为新ManualResetEvent(错误)
私有addLogQueue作为新队列
私有关闭为布尔值=false
公用支线
1.开始
端接头
公共子addLogHandler(ByVal machineName作为字符串,ByVal LogTime作为日期,ByVal EventLog作为字符串,ByVal EventValue作为字符串)
Enqueue(“插入…一些SQL代码”)
mre.Set()
端接头
私有子addLog()
将cmdString设置为字符串
尝试
使用SQLCon作为新的SQLConnection
SQLCon.Open()
而不是关机
韦通先生()
mre.Reset()
同时添加日志队列。计数0
cmdString=addLogQueue.Dequeue()
SQLCmd=新的SqlCommand(cmdString,SQLCon)
SQLCmd.ExecuteNonQuery()
结束时
结束时
终端使用
特例
My.Application.Log.WriteException(例如,TraceEventType.Error,cmdString)
结束尝试
端接头

此外,如果您希望程序执行无人值守的监视,您可能需要查找一些关于编写服务的文章,因为这类事情作为一项服务工作得更好。另外,您可以让一个线程接受命令字符串并将其添加到队列中,第二个线程将其写入数据库。

这看起来像是一个问题。他们可能会指出您忘记执行
SQLConn.Dispose()
@AndrewMorton,他更可能使用
使用
指令。(几乎从来没有必要这样写。)@EBrown我打算把大部分内容留给代码审查,在那里还可以讨论使用队列的优点。这看起来像是一个问题。他们可能会指出您忘记执行
SQLConn.Dispose()
@AndrewMorton,他更可能使用
使用
指令。(几乎没有必要这样写。)@EBrown我打算把大部分内容留给代码审查,在那里还可以讨论使用队列的优点。感谢描述中的链接。我把同样的问题贴到了网上