I've just inherited a legacy VB.Net project which runs fine in VS Community 2017 on a machine on the client's network, but when I try and run the code locally (on VS2017 Pro) I get an exception.
The project has the following properties set:
The code in SetupWizard form's load event checks a few thing and then closes itself if they are OK and opens another form:
Private Sub SetupWizard_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
If [some conditions] Then
frmMain.Show()
Me.Close()
Else
I'm getting this error when execution exits the SetupWizard_Load
if the conditions are met and me.close
is called:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll Cross-thread operation not valid: Control 'SplashInvoice' accessed from a thread other than the thread it was created on.
If I comment out the me.close
bit it all works fine.
So, it seems like closing the project's startup form while the project's splash screen is still showing is the issue, which leads to a couple of questions:
This is the full stack trace:
System.Transactions Critical: 0 : http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/UnhandledUnhandled exceptionInvoice Generator.exeSystem.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Cross-thread operation not valid: Control 'SplashInvoice' accessed from a thread other than the thread it was created on. at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.Form.Activate() 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.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)System.InvalidOperationException: Cross-thread operation not valid: Control 'SplashInvoice' accessed from a thread other than the thread it was created on. at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.Form.Activate() 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.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll Cross-thread operation not valid: Control 'SplashTest' accessed from a thread other than the thread it was created on.The program '[50096] Invoice Generator.exe' has exited with code -1 (0xffffffff).
Before really understanding what was going on here I did manage to stop the exception by manually closing the splash screen in the start up form's Load
event. I added a call to the following method into that event:
private sub CloseSplash()
Dim mySplash = My.Application.OpenForms.Item("SplashInvoice")
mySplash.Invoke(New MethodInvoker(Sub()
mySplash.Close()
mySplash.Dispose()
End Sub))
End sub
That code is based on this answer.
@TnTinMn then provided some really useful information on all of this the comments and led to me to the Microsoft documentation on Extending the Visual Basic Application Model
That has this excellent diagram to explain how it all wires together:
That article also states
ShowSplashScreen. Determines if the application has a splash screen defined and if it does, displays the splash screen on a separate thread.
Which appears to the be root of the issue I'm seeing.
@TnMinMn also made some really useful suggestions on how to fix this issue:
Personally, I would disable the Application Framework and use a Sub Main to launch a customized version of Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase. That way you could set the MainForm based on your some conditions, while still utilizing the base splash screen support, instead of creating a form that never shows when some conditions is true
User contributions licensed under CC BY-SA 3.0