Vb.net 使用线程更新datagridview

Vb.net 使用线程更新datagridview,vb.net,datagridview,thread-safety,Vb.net,Datagridview,Thread Safety,我在按钮处有以下代码。单击sub,它从一个access DB获取数据,并将行逐个加载到SQL DB中,插入代码的行会被注释,因为它已经过测试 Dim cSQL As New SqlConnection(conSQL) Dim fecha1, fecha2 As Date Dim strfecha1, strfecha2 As String For Each dr As DataRow In dt.Rows fecha1 = CDate(dr.Item(0)

我在按钮处有以下代码。单击sub,它从一个access DB获取数据,并将行逐个加载到SQL DB中,插入代码的行会被注释,因为它已经过测试

Dim cSQL As New SqlConnection(conSQL)
    Dim fecha1, fecha2 As Date
    Dim strfecha1, strfecha2 As String
    For Each dr As DataRow In dt.Rows
        fecha1 = CDate(dr.Item(0))
        fecha2 = CDate(dr.Item(18))
        strfecha1 = fecha1.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        strfecha2 = fecha2.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        selSQL = "insert into ttransactionlog1 ([OccurDateTime],[NodeID],[Kind],[UUID],[UserID],[FirstName],[LastName],[MI],[Department],[Rank],[CardID],[CreateDateTime],[LeftRight],[HD],[RotationDegree],[StableTimeInterval],[DecisionTimeInterval],[Message],[PIN]) values " + _
            "('" + strfecha1 + "'," + _
            dr.Item(1).ToString + "," + _
            dr.Item(2).ToString + "," + _
            dr.Item(4).ToString + ",'" + _
            dr.Item(3).ToString + "','" + _
            dr.Item(5).ToString + "','" + _
            dr.Item(6).ToString + "','" + _
            dr.Item(7).ToString + "','" + _
            dr.Item(8).ToString + "','" + _
            dr.Item(9).ToString + "','" + _
            dr.Item(10).ToString + "','" + _
            strfecha2 + "'," + _
            dr.Item(16).ToString + "," + _
            dr.Item(14).ToString + "," + _
            dr.Item(15).ToString + "," + _
            dr.Item(12).ToString + "," + _
            dr.Item(13).ToString + ",'" + _
            dr.Item(11).ToString + "'," + _
            dr.Item(17).ToString + ")"
        daSQL.InsertCommand = New SqlCommand(selSQL, cSQL)
        'cSQL.Open()
        'daSQL.InsertCommand.ExecuteNonQuery()
        'cSQL.Close()
        'DataGridView1.Rows.Insert(0, dr.ItemArray)
        'If DataGridView1.Rows.Count > 10 Then
        '    DataGridView1.Rows.RemoveAt(10)
        'End If
        procesar = New Thread(AddressOf Me.actGrilla)
        procesar.IsBackground = True
        procesar.Start(dr)
        'actGrilla(dr)
    Next
我想更新一个DGV,在它的顶部位置显示插入的数据行,并在屏幕上显示多达10条记录,为此,我正试图以这种方式在一个新线程中创建一个子线程

Sub actGrilla(ByVal dr As DataRow)
    If InvokeRequired Then
        Dim uud As New llamaactGrilla(AddressOf actGrilla)
        Invoke(uud, dr)
    Else
        DataGridView1.Rows.Insert(0, dr.ItemArray)
        If DataGridView1.Rows.Count > 10 Then
            DataGridView1.Rows.RemoveAt(10)
        End If
        DataGridView1.Refresh()
    End If
End Sub
我的问题是,当我尝试这种方式时,代码总是按invokererequired true执行,并按内存错误崩溃(大约5000条记录),当我尝试在没有线程的情况下执行时,在循环中编写“else”代码,程序最终会因cotextswitchdeadlock崩溃


我做错了什么?

我没有使用
invokererequired
。Windows有一个新的功能,可以使对UI控件的线程访问更加容易。我不精通VB.Net,但我想尝试一下:

Dim Sync as SynchronizationContext = SynchronizationContext.Current

Sub actGrilla(ByVal dr As DataRow)
    // Post is an async method that queues work on the UI thread
    // Alternatively, use Send instead as a blocking call
    Sync.Post(
          // I do not know the correct syntax in VB to set this up  
//但是


稍加研究,问题就解决了

第一。我用thead调用替换循环

    If dt.Rows.Count > 0 Then
        procesar = New Thread(AddressOf procesoFondo)
        procesar.Start(dt)
    End If
第二。将循环放在新函数“procesoFondo”中,在SQL DB中插入代码的行在这里,放入我调用新子委托的循环中

    Dim daSQL As New SqlDataAdapter

    Dim cSQL As New SqlConnection(conSQL)
    Dim fecha1, fecha2 As Date
    Dim strfecha1, strfecha2 As String
    For Each dr As DataRow In dt.Rows
        fecha1 = CDate(dr.Item(0))
        fecha2 = CDate(dr.Item(18))
        strfecha1 = fecha1.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        strfecha2 = fecha2.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        selSQL = "insert into ttransactionlog1 ([OccurDateTime],[NodeID],[Kind],[UUID],[UserID],[FirstName],[LastName],[MI],[Department],[Rank],[CardID],[CreateDateTime],[LeftRight],[HD],[RotationDegree],[StableTimeInterval],[DecisionTimeInterval],[Message],[PIN]) values " + _
            "('" + strfecha1 + "'," + _
            dr.Item(1).ToString + "," + _
            dr.Item(2).ToString + "," + _
            dr.Item(4).ToString + ",'" + _
            dr.Item(3).ToString + "','" + _
            dr.Item(5).ToString + "','" + _
            dr.Item(6).ToString + "','" + _
            dr.Item(7).ToString + "','" + _
            dr.Item(8).ToString + "','" + _
            dr.Item(9).ToString + "','" + _
            dr.Item(10).ToString + "','" + _
            strfecha2 + "'," + _
            dr.Item(16).ToString + "," + _
            dr.Item(14).ToString + "," + _
            dr.Item(15).ToString + "," + _
            dr.Item(12).ToString + "," + _
            dr.Item(13).ToString + ",'" + _
            dr.Item(11).ToString + "'," + _
            dr.Item(17).ToString + ")"

        'Inserta el dato en SQL
        daSQL.InsertCommand = New SqlCommand(selSQL, cSQL)
        cSQL.Open()
        daSQL.InsertCommand.ExecuteNonQuery()
        cSQL.Close()

        'Llama invocacion de llenado de gridview
        add_datos_gv(dr)

        'Llama invocacion estado proceso
        estado_hilo()
    Next
代理(显示线程状态的标签为1+)为

最后,代理更新DGV中的信息

 Private Sub add_datos_gv(ByVal dr As DataRow)
    If DataGridView1.InvokeRequired Then
        Dim d As New set_gv(AddressOf add_datos_gv)
        Invoke(d, dr)
    Else
        DataGridView1.Rows.Insert(0, dr.ItemArray)
        If DataGridView1.Rows.Count > 10 Then
            DataGridView1.Rows.RemoveAt(10)
        End If
    End If
End Sub

Private Sub estado_hilo()
    If Label1.InvokeRequired Then
        Dim l As New set_lb(AddressOf estado_hilo)
        Invoke(l)
    Else
        Label1.Text = procesar.ThreadState.ToString
    End If
End Sub

什么版本的.Net?代码是在.NET3.5中编写的。我建议你找一个后台工作人员,经常使用它们,在我做的任何事情中都能很好地工作。
    Dim daSQL As New SqlDataAdapter

    Dim cSQL As New SqlConnection(conSQL)
    Dim fecha1, fecha2 As Date
    Dim strfecha1, strfecha2 As String
    For Each dr As DataRow In dt.Rows
        fecha1 = CDate(dr.Item(0))
        fecha2 = CDate(dr.Item(18))
        strfecha1 = fecha1.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        strfecha2 = fecha2.ToString("yyyyMMdd hh:mm:ss tt").Replace(".", "")
        selSQL = "insert into ttransactionlog1 ([OccurDateTime],[NodeID],[Kind],[UUID],[UserID],[FirstName],[LastName],[MI],[Department],[Rank],[CardID],[CreateDateTime],[LeftRight],[HD],[RotationDegree],[StableTimeInterval],[DecisionTimeInterval],[Message],[PIN]) values " + _
            "('" + strfecha1 + "'," + _
            dr.Item(1).ToString + "," + _
            dr.Item(2).ToString + "," + _
            dr.Item(4).ToString + ",'" + _
            dr.Item(3).ToString + "','" + _
            dr.Item(5).ToString + "','" + _
            dr.Item(6).ToString + "','" + _
            dr.Item(7).ToString + "','" + _
            dr.Item(8).ToString + "','" + _
            dr.Item(9).ToString + "','" + _
            dr.Item(10).ToString + "','" + _
            strfecha2 + "'," + _
            dr.Item(16).ToString + "," + _
            dr.Item(14).ToString + "," + _
            dr.Item(15).ToString + "," + _
            dr.Item(12).ToString + "," + _
            dr.Item(13).ToString + ",'" + _
            dr.Item(11).ToString + "'," + _
            dr.Item(17).ToString + ")"

        'Inserta el dato en SQL
        daSQL.InsertCommand = New SqlCommand(selSQL, cSQL)
        cSQL.Open()
        daSQL.InsertCommand.ExecuteNonQuery()
        cSQL.Close()

        'Llama invocacion de llenado de gridview
        add_datos_gv(dr)

        'Llama invocacion estado proceso
        estado_hilo()
    Next
Delegate Sub set_gv(ByVal dr As DataRow)
Delegate Sub set_lb()
 Private Sub add_datos_gv(ByVal dr As DataRow)
    If DataGridView1.InvokeRequired Then
        Dim d As New set_gv(AddressOf add_datos_gv)
        Invoke(d, dr)
    Else
        DataGridView1.Rows.Insert(0, dr.ItemArray)
        If DataGridView1.Rows.Count > 10 Then
            DataGridView1.Rows.RemoveAt(10)
        End If
    End If
End Sub

Private Sub estado_hilo()
    If Label1.InvokeRequired Then
        Dim l As New set_lb(AddressOf estado_hilo)
        Invoke(l)
    Else
        Label1.Text = procesar.ThreadState.ToString
    End If
End Sub