我有一个应用程序,该应用程序的形式是将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将应用程序视为无响应并使其崩溃?如果是这样,有没有更好的方法可以处理这些更新?
任何解决此问题的帮助将不胜感激。