0

I have the following code at button.click sub, it takes data from one access DB and load the rows one by one into a SQL DB, the line that inserts code is commented because it's already tested.

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

I want to update a DGV showing the inserted datarow in it's top position and up to 10 records in screen, for that I'm trying to make a sub in a new thread in this way.

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

My problem is when I try this way, the code always gone by invokeRequired true and collapse by memory fault (are about 5000 records), and when I try doing without a thread, writing the "else" code inside the for cycle the program eventually collapse with cotextswitchdeadlock.

What I'm doing wrong?

4

2 回答 2

1

稍加研究,问题就解决了。

第一个。我用 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+ 表示线程状态的标签)是。

Delegate Sub set_gv(ByVal dr As DataRow)
Delegate Sub set_lb()

最后,代表们更新了 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
于 2013-05-02T15:32:01.500 回答
0

我不使用InvokeRequired. WindowsSynchronizationContext可以使线程访问 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  

// but here is a sample

        DataGridView1.Rows.Insert(0, dr.ItemArray)
        If DataGridView1.Rows.Count > 10 Then
            DataGridView1.Rows.RemoveAt(10)
        End If
        DataGridView1.Refresh()
     , Nothing)
End Sub
于 2013-04-30T20:10:56.663 回答