辅助线程导致即使调用

时间:2019-04-26 13:23:33

标签: vb.net multithreading

我有一个应用程序,该应用程序的形式是将DataGridView绑定到BindingSource,而BindingSource绑定到DataTable:

bsList.DataSource = dsData
bsList.DataMember = "List"
dgvList.DataSource = bsList

填充dsData.Tables("List")的基础数据可以在用户工作时更改,因此,为了解决这个问题,我有一个后台线程,该线程定期检查数据库中的更改和更新dsData.Tables("List")。它还会更改其他用户当前正在工作的任何行的颜色。

但是,用户报告说,启用此后台更新功能后,应用程序会常规执行CTD,而不会出现应用程序错误消息。我无法重现此错误,由于从未写入日志文件,这表明从未触发过该事件,因此我尝试通过写入Private Sub MyApplication_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException中的日志文件来记录崩溃的尝试没有成功。

线程是这样实例化的:

LiveUpdating = New Thread(AddressOf UpdateUserLocation) With {.IsBackground = True}
LiveUpdating.Start()

这是UpdateUserLocation子:

Public Sub UpdateUserLocation()

Do While My.Settings.customBackgroundUpdating = True And formLoaded = True

UserLocations.Clear()
dtUsers = CLS_USERS.GetUsersSequence(winUser)
dtProgress = DAC.GetProgress()

For Each CandRow As DataRow In dsHHData.Tables("List").Rows

    Dim CandReadDate As Date
    Dim CandRowNextRead As String = DBNull.Value.ToString

    If Not (CandRow("NEXT READ").ToString = DBNull.Value.ToString) Then
        If Date.TryParse(CandRow("NEXT READ").ToString, CandReadDate) Then
            CandRowNextRead = CandReadDate.ToString("dd/MM/yyyy")
        End If
    End If

    Dim CandRowSending As String = TryCast(CandRow("SENDING"), String)
    Dim CandRowNotes As String = TryCast(CandRow("NOTES"), String)

    For Each NewRow As DataRow In dtUsers.Rows
        If CandRow("SQ").ToString = NewRow("SQ").ToString Then
            UserLocations.Add(NewRow("SQ").ToString)
        End If
    Next

    For Each ProgressRow As DataRow In dtProgress.Rows
        If CandRow("SQ").ToString = ProgressRow("SQ").ToString Then

            Dim NextReadDate As Date
            Dim ProgressRowNextRead As String = DBNull.Value.ToString

            If Not (ProgressRow("NEXT READ").ToString = DBNull.Value.ToString) Then
                If Date.TryParse(ProgressRow("NEXT READ").ToString, NextReadDate) Then
                    ProgressRowNextRead = NextReadDate.ToString("dd/MM/yyyy")
                End If
            End If

            Dim ProgressRowSending As String = TryCast(ProgressRow("SENDING"), String)
            Dim ProgressRowNotes As String = TryCast(ProgressRow("NOTES"), String)

            If CandRow("SQ").ToString = ProgressRow("SQ").ToString Then

                If CandRowSending <> ProgressRowSending Then
                    BeginInvoke(New UpdateDataTableDelegate(AddressOf UpdateDataTableSending), CandRow, ProgressRowSending)
                End If

                If CandRowNextRead <> ProgressRowNextRead Then
                    BeginInvoke(New UpdateDataTableDelegate(AddressOf UpdateDataTableNextRead), CandRow, ProgressRowNextRead)
                End If

                If CandRowNotes <> ProgressRowNotes Then
                    BeginInvoke(New UpdateDataTableDelegate(AddressOf UpdateDataTableNotes), CandRow, ProgressRowNotes)
                End If

            End If
        End If
    Next
Next

dgv.BeginInvoke(
    New MethodInvoker(
    Sub()
        For Each dgv_row As DataGridViewRow In dgv.Rows
            If UserLocations.Contains(dgv_row.Cells("SQ").Value.ToString) Then
                dgv.DefaultCellStyle.BackColor = My.Settings.customRowHighlight
            Else
                dgv.DefaultCellStyle.BackColor = Nothing
            End If
        Next
    End Sub))

Thread.Sleep(My.Settings.customRefreshRate * 1000)

Loop

End Sub

执行DataTable更新的子项如下:

Private Delegate Sub UpdateDataTableDelegate(ByVal CandRow As DataRow, ByVal ProgressRow As String)
Private Sub UpdateDataTableSending(ByVal CandRow As DataRow, ByVal ProgressRowSending As String)
        CandRow("SENDING") = ProgressRowSending
    End Sub

我知道这不是处理多用户环境的最佳方法,但是这项工作的本质要求所有人都可以访问并看到相同的数据。我可以强迫他们定期刷新,但这似乎很麻烦。

仅当此线程正在运行并且崩溃是常规的(而不是瞬时的)时,才会发生崩溃,但是我似乎无法重现它们,否则应用程序将非常稳定。

必须存在一些跨线程问题,但是当通过主UI线程上的BeginInvoke完成对DataTable或DataGridView的所有更新时,我无法工作。

编辑:我刚刚意识到,即使我在后台线程中执行查询和大部分繁重的工作,更新仍在主UI线程上被调用,这将锁定该线程。如果有很多更新,这将尤其明显...因为每个更新都是单独调用的。 如果UI锁定时间足够长,并且用户单击了内容,这是否会使Windows将应用程序视为无响应并使其崩溃?如果是这样,有没有更好的方法可以处理这些更新?

任何解决此问题的帮助将不胜感激。

0 个答案:

没有答案