我正在开发一个Windows表单应用程序来轮询信息(RFID标签)并在datagridview中显示它们。我还希望用户能够随时启动和停止轮询,因此我使用了一个Task来处理轮询。 由于Task创建了另一个线程,我将主线程的上下文传递给我创建的线程(允许它修改主线程资源和ui)
我的问题: 第一次轮询正确完成,任务找到TAG,将其插入我的DataGridView,UI显示信息。 但是,当我的轮询尝试插入新TAGS时,问题就出现了,它正确地将它们插入到DataGridView.DataSource中,但它永远不会更新UI并在DataGridView中显示新元素
我无法理解为什么它第一次正确完成,但在任何其他时间错误地完成。
我的代码在这里:
Dim lstTags As List(Of CustomTag)
Dim MsSleep As Integer = 1000
Public primaryTokenSource As CancellationTokenSource
Private Sub btnStartPolling_Click(sender As System.Object, e As System.EventArgs) Handles btnStartPolling.Click
btnStopPolling.Visible = True
primaryTokenSource = New CancellationTokenSource()
Dim context As TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
Dim ct As CancellationToken = primaryTokenSource.Token
Task.Factory.StartNew(Sub()
ct.ThrowIfCancellationRequested()
PollRFID(context, ct, MsSleep)
End Sub)
End Sub
Private Sub PollRFID(context As TaskScheduler, ct As CancellationToken, MsSleep As Integer)
Try
While True
' Check if the stop button has been pushed
If (ct.IsCancellationRequested) Then ct.ThrowIfCancellationRequested()
' Check if we find any new TAG
Dim TagID As String = ""
' TagID is read ByRef
_reader.ReadRFID(TagID)
If TagID <> "" Then
' CustomTag is a class With a string TagID and a Date InsertDate
Dim tc As New CustomTag
tc.Tag = TagID
tc.InsertDate = Now
lstTags.Add(tc)
Task.Factory.StartNew(Sub()
grdTags.DataSource = lstTags
grdTags.Refresh()
End Sub,
CancellationToken.None,
TaskCreationOptions.LongRunning,
context)
End If
Thread.Sleep(MsSleep)
End While
Catch ex As Exception
End Try
End Sub
Private Sub btnStopPolling_Click(sender As System.Object, e As System.EventArgs) Handles btnStopPolling.Click
primaryTokenSource.Cancel()
btnStopPolling.Visible = False
End Sub
答案 0 :(得分:0)
grdTags.Refresh()
只重绘对象但不刷新基础日期(我真的希望他们会对此做些什么,经常发生)。
尝试使用BindingSource
代替。另一种解决方案是将datagrid的DataSource设置为null,然后设置为您想要的实际数据源。
答案 1 :(得分:0)
所以我终于找到了解决方案(我整个周末都在考虑这个问题,就像我发布的那样,半小时后我找到了解决方案:p)
我的解决方案是: Task.Factory.StartNew(子() 'grdTags.Rows.Clear() grdTags.DataSource =没什么 'grdTags.DataSource = BindingSource grdTags.DataSource = lstTags grdTags.ResetBindings() grdTags.Refresh() End Sub, CancellationToken.None, TaskCreationOptions.LongRunning, 上下文中)
只需将DataGridView中的DataSource设置为Nothing
即可grdTags.DataSource = Nothing
然后使用新列表
更新数据源 grdTags.DataSource = lstTags