Solved

DataGridView InvalidOperationException

Posted on 2010-11-12
9
643 Views
Last Modified: 2012-05-11
I have a datagridview whose datasource is a bindingsource linked to a datatable in a dataset.

From a background worker, I want to add rows to the table then refresh the datagridview to reflect the updates.

Here's what I have so far:
 
Private Delegate Sub AddEntryCallback(ByVal Entry As SearchResultEntry)
  Private Delegate Sub RefreshDisplayCallback()

  Private Sub bwPageSearch_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwPageSearch.DoWork
     
'.....'

      Dim AddEntry As AddEntryCallback = AddressOf AddEntryToTable
      Dim UpdateDisplay As RefreshDisplayCallback = AddressOf RefreshDisplay

'.....'

          For Each entry As SearchResultEntry In Response.Entries
            If dgvADSI.InvokeRequired Then
              AddEntry.Invoke(entry)
            Else
              AddEntryToTable(entry)
            End If
            If dgvADSI.InvokeRequired Then
              UpdateDisplay.Invoke()
            Else
              RefreshDisplay()
            End If
          Next

'.....'

  End Sub

  Private Sub AddEntryToTable(ByVal Entry As SearchResultEntry)

    Try
      Dim tmpDataRow As DataRow = dtADSI.NewRow

      If Entry.Attributes.Contains("displayname") Then tmpDataRow.Item("Name") = Entry.Attributes.Item("displayname").Item(0).ToString
      If Entry.Attributes.Contains("mail") Then tmpDataRow.Item("E-Mail Address") = Entry.Attributes.Item("mail").Item(0).ToString
      If Entry.Attributes.Contains("telephonenumber") Then tmpDataRow.Item("Business Phone") = Entry.Attributes.Item("telephonenumber").Item(0).ToString
      If Entry.Attributes.Contains("homephone") Then tmpDataRow.Item("Home Phone") = Entry.Attributes.Item("homephone").Item(0).ToString
      If Not String.IsNullOrEmpty(Entry.DistinguishedName.Trim) Then tmpDataRow.Item("adsPath") = Entry.DistinguishedName.ToString
      dtADSI.Rows.Add(tmpDataRow)
      dtADSI.AcceptChanges()
      tmpDataRow = Nothing
    Catch ex As Exception
      MsgBox("AddEntryToTable: " & NewLine() & ex.Message)
    End Try

  End Sub 

  Private Sub RefreshDisplay()

    Try
      If dtADSI.Rows.Count > 0 Then
        Try
          If Not dgvADSI.Visible Then
            'Cross-thread errors happen on any of these lines of code'
            Me.MaximumSize = New Size(intResultsMaxFrmWt, intResultsMaxFrmHt)
            Me.MinimumSize = New Size(intResultsFrmWt, intResultsFrmHt)
            dgvADSI.AutoResizeColumns()
            dgvAHCS.Visible = False
            dgvADSI.Visible = True
          End If
        Catch ex As Exception
          MsgBox("Not dgvADSI.Visible: " & NewLine() & ex.Message)
        End Try
        dtADSI.AcceptChanges()
        Try
          dgvADSI.Invalidate()
        Catch ex As Exception
          MsgBox("dgvADSI.Invalidate: " & NewLine() & ex.Message)
        End Try
      End If
    Catch ex As Exception
      MsgBox("dtADSI.Rows.Count: " & NewLine() & ex.Message)
    End Try

  End Sub

Open in new window


Problem is, I'm getting Cross-thread errors when the code tries to resize the form or modify the datagridview.  I know that the section of code is being invoked, due to debugging I've put in.  What am I missing and need to do to get this to work?
0
Comment
Question by:rogerard
  • 7
  • 2
9 Comments
 
LVL 7

Author Comment

by:rogerard
ID: 34123056
I've made some progress:

I've replaced  
Me.MaximumSize = New Size(intResultsMaxFrmWt, intResultsMaxFrmHt)
Me.MinimumSize = New Size(intResultsFrmWt, intResultsFrmHt)
dgvADSI.AutoResizeColumns()
dgvAHCS.Visible = False
dgvADSI.Visible = True

Open in new window

with  
updateUI(Me, "MaximumSize", New Size(intResultsMaxFrmWt, intResultsMaxFrmHt))
updateUI(Me, "MinimumSize", New Size(intResultsFrmWt, intResultsFrmHt))
dgvADSI.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
updateUI(dgvAHCS, "Visible", False)
updateUI(dgvADSI, "Visible", True)

Open in new window

Private Delegate Sub UpdateUICallback(ByVal ctrl As Control, ByVal prop As String, ByVal value As Object)
  
Private Sub updateUI(ByVal ctrl As Control, ByVal prop As String, ByVal value As Object)
    Try
      If ctrl.InvokeRequired = True Then
        Dim d As New UpdateUICallback(AddressOf updateUI)
        ctrl.Invoke(d, ctrl, prop, value)
      Else
        ctrl.GetType.GetProperty(prop).SetValue(ctrl, value, Nothing)
      End If
    Catch ex As Exception
      MsgBox(ex.Message)
    End Try
  End Sub

Open in new window

The invalidate didn't work, so I also replaced
dgvADSI.Invalidate
with
dgvADSI.Refresh()
Now, the crossthread error occurs on the refresh.  
0
 
LVL 7

Author Comment

by:rogerard
ID: 34123317
More progress.

I replaced
dgvADSI.Refresh()
With
ctlMethod(dgvADSI, "refresh")

Now, there's no exceptions, but the datagridview still is not refreshing.
Private Delegate Sub ctlMethodCallback(ByVal ctrl As Control, ByVal Method As String)

  Private Sub ctlMethod(ByVal ctrl As Control, ByVal Method As String)



    Try

      If ctrl.InvokeRequired Then

        Try

          Dim d As New ctlMethodCallback(AddressOf ctlMethod)

          ctrl.Invoke(d, ctrl, Method)

        Catch ex As Exception

          MsgBox("Unable to invoke: " & NewLine & ex.Message)

        End Try

      Else

        ctrl.GetType.GetMethod(Method)

      End If

    Catch ex As Exception

      MsgBox("Unable to appy method: " & NewLine & ex.Message)

    End Try



  End Sub

Open in new window

0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 34127869
When do you need to update the DataGridView?  If you need to update it after the BackgroundWorker is done, then I would make the call from the RunWorkerCompleted event.
0
 
LVL 7

Author Comment

by:rogerard
ID: 34128984
I'm trying to update the datagridview as the data is being added to the datatable.  I suspect it has something to with making the datatable sync information across threads, but I'm not sure how to do that.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 96

Expert Comment

by:Bob Learned
ID: 34129093
How many rows are you getting for the DataGridView?  Is this a long running process, and you want to refresh the DataGridView after each "block" of data?
0
 
LVL 7

Author Comment

by:rogerard
ID: 34129222
On narrow queries, the results return and populate quickly.  On the broader queries, it can take up to a minute.   I'm trying to replicate, somewhat, the people search form when you click start>Search>People to add a few more capabilities and search locations specific to my company.  I have a active directory search set up using s.ds.p and returning paged results within a background worker, with a page size of 10, for results up to several thousand, possibly, depending on the search criteria.   I'm just not able to get the thread to update the dataset and refresh the datagridview the same way that the MS people search does on large results.

0
 
LVL 7

Assisted Solution

by:rogerard
rogerard earned 0 total points
ID: 34138550
I think I figured it out finally. Here's my final code.


Private Delegate Sub RefreshInvoker()

  Private Delegate Sub AutoResizeColumnsInvoker()



  Private Sub bwPageSearch_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwPageSearch.DoWork

          

          '........'



          For Each entry As SearchResultEntry In Response.Entries

            AddEntryToTable(entry)

          Next



          '........'



End sub



  Private Sub AddEntryToTable(ByVal Entry As SearchResultEntry)



    Try

      Dim tmpDataRow As DataRow = dtADSI.NewRow

      If Entry.Attributes.Contains("displayname") Then tmpDataRow.Item("Name") = Entry.Attributes.Item("displayname").Item(0).ToString

      If Entry.Attributes.Contains("mail") Then tmpDataRow.Item("E-Mail Address") = Entry.Attributes.Item("mail").Item(0).ToString

      If Entry.Attributes.Contains("telephonenumber") Then tmpDataRow.Item("Business Phone") = Entry.Attributes.Item("telephonenumber").Item(0).ToString

      If Entry.Attributes.Contains("homephone") Then tmpDataRow.Item("Home Phone") = Entry.Attributes.Item("homephone").Item(0).ToString

      If Not String.IsNullOrEmpty(Entry.DistinguishedName.Trim) Then tmpDataRow.Item("adsPath") = Entry.DistinguishedName.ToString

      dtADSI.Rows.Add(tmpDataRow)

      dtADSI.AcceptChanges()

      tmpDataRow = Nothing

      RefreshDisplay()

    Catch ex As Exception

      MsgBox("AddEntryToTable: " & NewLine() & ex.Message)

    End Try



  End Sub



  Private Sub RefreshDisplay()



    Try

      If dtADSI.Rows.Count > 0 Then

        If Not dgvADSI.Visible Then

          updateUI(Me, "MaximumSize", New Size(intResultsMaxFrmWt, intResultsMaxFrmHt))

          updateUI(Me, "MinimumSize", New Size(intResultsFrmWt, intResultsFrmHt))

          If dgvADSI.InvokeRequired Then

            dgvADSI.Invoke(New AutoResizeColumnsInvoker(AddressOf dgvADSI.AutoResizeColumns))

          Else

            dgvADSI.AutoResizeColumns()

          End If

          updateUI(dgvAHCS, "Visible", False)

          updateUI(dgvADSI, "Visible", True)

          dgvADSI.Sort(dgvADSI.Columns(0), System.ComponentModel.ListSortDirection.Ascending)

        End If

        If dgvADSI.InvokeRequired Then

          dgvADSI.Invoke(New RefreshInvoker(AddressOf dgvADSI.Refresh))

        Else

          dgvADSI.Refresh()

        End If

      End If

    Catch ex As Exception

      MsgBox("dtADSI.Rows.Count: " & NewLine() & ex.Message)

    End Try



  End Sub



  Private Sub RefreshDisplay()



    Try

      If dtADSI.Rows.Count > 0 Then

        If Not dgvADSI.Visible Then

          updateUI(Me, "MaximumSize", New Size(intResultsMaxFrmWt, intResultsMaxFrmHt))

          updateUI(Me, "MinimumSize", New Size(intResultsFrmWt, intResultsFrmHt))

          If dgvADSI.InvokeRequired Then

            dgvADSI.Invoke(New AutoResizeColumnsInvoker(AddressOf dgvADSI.AutoResizeColumns))

          Else

            dgvADSI.AutoResizeColumns()

          End If

          updateUI(dgvAHCS, "Visible", False)

          updateUI(dgvADSI, "Visible", True)

          dgvADSI.Sort(dgvADSI.Columns(0), System.ComponentModel.ListSortDirection.Ascending)

        End If

        If dgvADSI.InvokeRequired Then

          dgvADSI.Invoke(New RefreshInvoker(AddressOf dgvADSI.Refresh))

        Else

          dgvADSI.Refresh()

        End If

      End If

    Catch ex As Exception

      MsgBox("dtADSI.Rows.Count: " & NewLine() & ex.Message)

    End Try



  End Sub

Open in new window

0
 
LVL 7

Accepted Solution

by:
rogerard earned 0 total points
ID: 34138862
Correction - Replace:
updateUI(Me, "MaximumSize", New Size(intResultsMaxFrmWt, intResultsMaxFrmHt))
          updateUI(Me, "MinimumSize", New Size(intResultsFrmWt, intResultsFrmHt))
          If dgvADSI.InvokeRequired Then
            dgvADSI.Invoke(New AutoResizeColumnsInvoker(AddressOf dgvADSI.AutoResizeColumns))
          Else
            dgvADSI.AutoResizeColumns()
          End If
          updateUI(dgvAHCS, "Visible", False)
          updateUI(dgvADSI, "Visible", True)
          dgvADSI.Sort(dgvADSI.Columns(0), System.ComponentModel.ListSortDirection.Ascending)

Open in new window

With:
 
updateUI(Me, "MaximumSize", New Size(intResultsMaxFrmWt, intResultsMaxFrmHt))
            updateUI(Me, "MinimumSize", New Size(intResultsFrmWt, intResultsFrmHt))
            updateUI(dgvAHCS, "Visible", False)
            updateUI(dgvADSI, "Visible", True)
              If dgvADSI.InvokeRequired Then
                dgvADSI.Invoke(New AutoResizeColumnsInvoker(AddressOf dgvADSI.AutoResizeColumns))
                dgvADSI.Invoke(New SortInvoker(AddressOf dgvADSI.Sort), dgvADSI.Columns(0), System.ComponentModel.ListSortDirection.Ascending)
              Else
                dgvADSI.AutoResizeColumns()
                dgvADSI.Sort(dgvADSI.Columns(0), System.ComponentModel.ListSortDirection.Ascending)
              End If

Open in new window

0
 
LVL 7

Author Closing Comment

by:rogerard
ID: 34995326
Answered my own question.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now