VB.net ApplicationFramework 加 SplashScreen:InvalidOperationException
我最近将我的应用程序从使用自定义 SplashScreen(它只是一个带有计时器的表单加载主表单并自行关闭)更改为应用程序框架。
这就是我所做的:
- 创建一个新的 SplashScreenForm,显示应用程序版本等。
- 在以下位置选择该表单:我的项目 ->应用-> SplashScreen
- 将长时间运行的初始化代码从主窗体的构造函数移动到 ApplicationEvents 启动事件
这完全符合我的要求。 SplashScreen 首先出现,然后启动事件触发并开始工作。 SplashScreen 关闭并显示实际的主窗体。
到目前为止,一切都很好。但我们的客户有时会在启动过程中遇到这种令人讨厌的异常:
System.InvalidOperationException: Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.
bei System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle)
bei System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
bei System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
bei System.Windows.Forms.Control.Invoke(Delegate method)
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen()
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object sender, EventArgs e)
bei System.EventHandler.Invoke(Object sender, EventArgs e)
bei System.Windows.Forms.Form.OnLoad(EventArgs e)
bei System.Windows.Forms.Form.OnCreateControl()
bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
bei System.Windows.Forms.Control.CreateControl()
bei System.Windows.Forms.Control.WmShowWindow(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
bei System.Windows.Forms.Form.WmShowWindow(Message& m)
bei System.Windows.Forms.Form.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
在 HideSplashScreen() 过程中似乎出现错误,但问题是整个堆栈超出了我的控制范围,因此我无法捕获此异常。
有什么建议吗?
I recently changed my app from using a custom SplashScreen (it was just a Form with a Timer loaded the main form and closed itself) to the Application Framework.
Here is what I did:
- Created a new SplashScreenForm that shows the app version etc.
- Selected that Form at: My Project -> Application -> SplashScreen
- Moved long running initialisation code from the constructor of the main form to the ApplicationEvents Startup Event
That totally does what I want. The SplashScreen shows up first, than the Startup Event fires and does it's work. The SplashScreen closes and the actual main forms shows up.
So far so good. But our customers sometimes get this nasty exception during Startup:
System.InvalidOperationException: Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.
bei System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle)
bei System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
bei System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
bei System.Windows.Forms.Control.Invoke(Delegate method)
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen()
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.MainFormLoadingDone(Object sender, EventArgs e)
bei System.EventHandler.Invoke(Object sender, EventArgs e)
bei System.Windows.Forms.Form.OnLoad(EventArgs e)
bei System.Windows.Forms.Form.OnCreateControl()
bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
bei System.Windows.Forms.Control.CreateControl()
bei System.Windows.Forms.Control.WmShowWindow(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
bei System.Windows.Forms.Form.WmShowWindow(Message& m)
bei System.Windows.Forms.Form.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
There seems to be an error during HideSplashScreen(), but the thing is that the whole stack is out of my control so I can't just catch this exception.
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
将其放入您的启动画面中。如果有一些组件,该子组件可能已在 Designer.vb 文件中声明。只需将其内容移至源代码并插入第一行即可。
我已经进行了深入分析,包括框架程序集的反编译,这应该可以解决问题。详细的解释会更长的故事。
我无法在自己的计算机上重现此问题,但在各种客户端计算机上都会出现错误。即使是恶意调用,似乎也无法重现。没有与硬件或软件相关的条件来模拟该问题,但当事件循环消息延迟并且工作线程在错误的时刻切换时,它通常发生在 CPU 使用率低或高的 PC 上。
Put this in your splash from. If there are some components, this sub might be already declared in Designer.vb file. Simply move it's content to your source code and insert first line.
I've run throught deep analyse including decompilation of framework assemblies and this should do the trick. Detailed explanation would be longer story.
I'm unable to reproduce this issue on my own computer, but error occurs on various client machines. It seems impossible to reproduce it even with malicious calls. There's no HW nor SW related condition to simulate the issue, but it usually occurs on slow or high CPU used PCs when event loop messages got delayed and working threads are switched in wrong moment.
InnerException
并确定您看到的错误是否确实是源错误,或者只是一个错误重新抛出。HTH
MyApplication class
?InnerException
s recursively and determine if the error you see is indeed the source error, or just a rethrow.HTH
这是我的解决方案。我最终只是吞下了 UnhandledException 事件中的任何 InvalidOperationException ,直到 SplashScreen 消失。
为此,我向 MyApplication 类添加了一个属性
MainFormLoadingComplete
,该属性在主窗体的 Shown 事件中设置为 true(闪屏一直保留到处理 Form_Load 事件为止)。我还发现我必须在
OnInitialize()
之前设置MinimumSplashScreenDisplayTime
才能生效。希望这有助于首先避免异常。但由于这个异常是完全随机的,我的SplashScreen 代码:
Form1 代码:
MyApplication 代码:
This is my solution. I ended with just swallowing any InvalidOperationException in the UnhandledException Event until the SplashScreen is gone.
To do that I added a Property
MainFormLoadingComplete
to my MyApplication class that is set to true in the Shown Event of my main form (the splashscreen stays until the Form_Load event is processed).I also figured out that I have to set
MinimumSplashScreenDisplayTime
beforeOnInitialize()
to be effective. Hopefully that helps avoiding the exception in the first place. But since this exception is totally random ISplashScreen code:
Form1 code:
MyApplication code:
刚刚遇到这个问题,我们使用相同的技术遇到了完全相同的问题。
我将尝试您的解决方案,但我只是想让您知道如何重现它:
我们的支持人员在这方面花费了大量时间,最终将其范围缩小到仅在 Windows 7 中发生,并且仅在 Windows 之后发生已经从开机启动了。
如果您重新启动 Windows,然后立即启动使用此启动屏幕技术的应用程序,则错误几乎总是会发生。
如果您重新启动 Windows,等待几分钟然后启动您的应用程序,您将永远不会看到该错误。
我通过在主窗体的加载事件底部放置 sleep(400) 来解决这个问题,但是有些人仍然看到错误,我将尝试您的解决方案。
just came across this, we have the exact same problem using the same technique.
I'm going to try your solution that works but I just wanted to let you know how to reproduce it:
Our support people spent a lot of time on this and finally narrowed it down to happening only in windows 7 and only happening just after windows has been started from boot.
If you reboot windows then immediately launch your app that uses this splash screen technique the error will happen almost all the time.
If you reboot windows, wait a few minutes then start your app you will never see the error.
I worked around it by putting in a sleep(400) at the bottom of my main form's load event, however some were still seeing the error and I'm going to try your solution instead.