我刚刚继承了一个旧版VB.Net项目,该项目可以在客户端网络上的计算机上的VS Community 2017中正常运行,但是当我尝试在本地(在VS2017 Pro上)运行代码时,会出现异常。
该项目设置了以下属性:
SetupWizard表单的load事件中的代码检查了几件事,如果确定还可以关闭自身,然后打开另一个表单:
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
如果满足条件并调用SetupWizard_Load
,则执行退出me.close
时出现此错误:
类型为'System.InvalidOperationException'的未处理异常 发生在System.Windows.Forms.dll跨线程操作无效: 从其他线程访问的控件“ SplashInvoice” 创建于。
如果我注释掉me.close
位,一切正常。
因此,似乎是在项目的启动画面仍显示时关闭项目的启动表单,这引发了两个问题:
这是完整的堆栈跟踪:
System.Transactions严重:0:http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled未处理 例外发票 Generator.exeSystem.InvalidOperationException, mscorlib,版本= 4.0.0.0,文化=中性, PublicKeyToken = b77a5c561934e089跨线程 操作无效:控件'SplashInvoice'从其他线程访问 比创建它的线程要多。在 System.Windows.Forms.Control.get_Handle()在 System.Windows.Forms.Form.Activate()在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen() 在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object 发送方,System.EventHandler.Invoke处的EventArgs e)(对象发送方, EventArgs e)位于System.Windows.Forms.Form.OnLoad(EventArgs e)位于 System.Windows.Forms.Form.OnCreateControl()在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
在System.Windows.Forms.Control.CreateControl()在 System.Windows.Forms.Control.WmShowWindow(Message&m)位于 System.Windows.Forms.Control.WndProc(Message&m)位于 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
在System.Windows.Forms.Form.WmShowWindow(Message&m)处 System.Windows.Forms.Form.WndProc(Message&m)位于 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)System.InvalidOperationException: 跨线程操作无效:从控件访问“ SplashInvoice” 创建线程以外的其他线程。在 System.Windows.Forms.Control.get_Handle()在 System.Windows.Forms.Form.Activate()在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen() 在 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object 发送方,System.EventHandler.Invoke处的EventArgs e)(对象发送方, EventArgs e)位于System.Windows.Forms.Form.OnLoad(EventArgs e)位于 System.Windows.Forms.Form.OnCreateControl()在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
在System.Windows.Forms.Control.CreateControl()在 System.Windows.Forms.Control.WmShowWindow(Message&m)位于 System.Windows.Forms.Control.WndProc(Message&m)位于 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
在System.Windows.Forms.Form.WmShowWindow(Message&m)处 System.Windows.Forms.Form.WndProc(Message&m)位于 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)未处理 类型“ System.InvalidOperationException”的异常发生在 System.Windows.Forms.dll跨线程操作无效:控件 从不是该线程的线程访问了'SplashTest' 创建于。程序“ [50096] Invoice Generator.exe”已退出,代码为-1 (0xffffffff)。
答案 0 :(得分:0)
在真正理解这里发生的事情之前,我确实设法通过在启动表单的Load
事件中手动关闭了启动屏幕来停止异常。我在该事件中添加了对以下方法的调用:
private sub CloseSplash()
Dim mySplash = My.Application.OpenForms.Item("SplashInvoice")
mySplash.Invoke(New MethodInvoker(Sub()
mySplash.Close()
mySplash.Dispose()
End Sub))
End sub
@TnTinMn然后提供了关于所有这些注释的一些非常有用的信息,并带我到Extending the Visual Basic Application Model上的Microsoft文档
该图中有一个很好的图来说明它们如何连接在一起:
该文章还指出
ShowSplashScreen。确定应用程序是否具有启动屏幕 已定义,如果已定义,则将启动屏幕显示在单独的屏幕上 线程。
这似乎是我所看到的问题的根源。
@TnMinMn还提出了一些有关如何解决此问题的非常有用的建议:
我个人将禁用应用程序框架并使用Sub 主要推出定制版 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase。 这样,您可以根据自己的条件设置MainForm, 同时仍在使用基本的初始屏幕支持,而不是 创建一个在某些条件为真时永远不会显示的表单