I have a VB.net program that has a splashscreen. While the main window is loading, I search the network with a multithreading solution I created. I.e. It calls two other classes that each send out a broadcast packet, parses it, and then sends it in a list back to the main window. Once that's done I make a datatable of it and send it to the datagridview on the GUI. I also adjust the datagridview's columns, and a few other visual things. This is all done in a function called updateTable()
Here's some code to give some perspective :
Private Sub MainWindow_Load(sender As Object, e As EventArgs) Handles Me.Load
'search network for data & update the datagridview's table
updateTable()
'fix label to show number of items found
lblCamNumber.Text = Me.devicesDataGridView.RowCount.ToString & " of devices Found"
End Sub
This setup was working fine originally, but I only recently added multithreading into the updateTable() function. Because of it, once in a blue moon I will get a BeginInvoke error. Saying, " cannot be called on a control until the window handle has been created."
From what I've seen on here, this usually means that I am trying to activate or adjust a control that hasn't been created yet in my splashscreen (there's no SQL server involved at all). I'm pretty certain this has to do with the way windows is initializing the form (i.e. from here A random cross-thread operation exception for Winforms multithreaded UI operation)
But I'm not calling (at least not in my code, windows may be) beginInvoke ever or any other lines. What can I do to my main window to make sure that this is fixed? Would moving the label update to another function help?
It should also be noted that the splashscreen has no code inside of its load function.
Here's a little bit of Updatetable() also,for clarity:
Private Function updateTable() As Boolean
'clean table
devicesDataGridView.DataSource = Nothing
'search for devices
Try
listOfdevices = searchNetwork()' <- multithreading is in here
Catch ex As Exception
Return False
End Try
'new datatable
Dim dt As DataTable = setupTable()
'add to datagridview
Dim i As Integer = 0
'add nothing if it is empty
If listOfdevices Is Nothing Then
Return True
End If
For Each d As device In listOfdevoces
'update table
dt.Rows.Add(False, i, d.hostname, d.brand, d.mac, d.model, d.firmware, _
d.ipaddr, d.port, d.ipgate, d.chan, d.encoder, _
d.DHCPen, d.MDen, d.OSD, d.res, d.bitrate, d.fps, _
d.audio, d.camtime, _
d.camdate, d.Username, d.Password, d.ResolutionsArray)
i = i + 1
Next
'################
'# Table Visuals
'################
'Column edit
With devicesDataGridView
Try
'assign data
devicesDataGridView.DataSource = dt
cleanupTable() 'clean up formatting, text color, etc
Catch ex As Exception
End Try
End With
Return True
End Function
EDIT:
Someone requested the full error:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle)
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object sender, EventArgs e)
at System.EventHandler.Invoke(Object sender, EventArgs e)
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)