1

I'm developing a windows forms application to poll information (RFID tags) and show them in a datagridview. I also wanted the users to be able to start and stop the polling whenever they wanted, so I used a Task to handle the polling. Since Task creates another thread, I passed the context of the main thread to the one I created (to allow it to modify the main thread resources and the ui)

My problem: The first poll is done correctly, the task finds a TAG, inserts it in my DataGridView and the UI shows the info. However, the problem appears when I my polling tries to insert new TAGS, it correctly inserts them in the DataGridView.DataSource, but it never gets to update the UI and show the new elements in the DataGridView

I can't understand why it's done correctly the first time, but wrongly any other time.

My code is here:

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
RdPC
  • 671
  • 10
  • 17

2 Answers2

0

grdTags.Refresh() only redraws the object but does not refresh the underlying date (I really wish they would do something about that, happens so often).

Try using a BindingSource instead. Another solution would be to set the DataSource of the datagrid to null and then to the actual datasource you want.

I wrote about it on this answer here https://stackoverflow.com/a/7079829/427684

Community
  • 1
  • 1
Paul C
  • 4,687
  • 5
  • 39
  • 55
  • Then I would suggest to strip the application down to the smallest amount of code possible that works. Than work from this and hopefully this should highlight the problem. Did you try setting it to null/nothing and then set the DataSource to what you want? – Paul C Feb 24 '14 at 09:29
  • Yes, that finally worked for me, don't really know why, but it did – RdPC Feb 24 '14 at 09:40
0

So i finally found a solution (I had been thinking about this problem all the weekend, and just as I post it, half an hour later I find a solution :p)

My solution was: Task.Factory.StartNew(Sub() ' grdTags.Rows.Clear() grdTags.DataSource = Nothing ' grdTags.DataSource = BindingSource grdTags.DataSource = lstTags grdTags.ResetBindings() grdTags.Refresh() End Sub, CancellationToken.None, TaskCreationOptions.LongRunning, context)

Just set the DataSource in the DataGridView to Nothing

grdTags.DataSource = Nothing

And then update the datasource with the new list

grdTags.DataSource = lstTags

RdPC
  • 671
  • 10
  • 17