我最近改变了我的应用程序,使用自定义SplashScreen(它只是一个表格,其中一个Timer加载了主窗体并自行关闭)到应用程序框架。
这是我做的:
这完全符合我的要求。 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()期间似乎有一个错误,但问题是整个堆栈都不受我的控制,所以我不能只捕获这个异常。
有什么建议吗?
答案 0 :(得分:5)
把它放在你的飞溅中。如果有一些组件,则此子组件可能已在Designer.vb文件中声明。只需将其内容移动到您的源代码并插入第一行。
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then My.Application.SplashScreen = Nothing
MyBase.Dispose(disposing)
End Sub
我已经深入分析了包括框架程序集的反编译,这应该可以解决问题。详细的解释将是更长的故事。
我无法在自己的计算机上重现此问题,但在各种客户端计算机上发生错误。即使使用恶意电话,也无法重现它。模拟问题没有硬件和软件相关的条件,但是当事件循环消息被延迟并且工作线程在错误的时刻切换时,它通常发生在慢速或高CPU使用的PC上。
答案 1 :(得分:1)
MyApplication class
?InnerException
并确定您看到的错误是否确实是源错误,或者只是重新抛出。HTH
Private Sub MyApplication_UnhandledException(
ByVal sender As Object,
ByVal e As ApplicationServices.UnhandledExceptionEventArgs) _
Handles Me.UnhandledException
Stop
End Sub
答案 2 :(得分:1)
这是我的解决方案。我最后只是在UnhandledException事件中吞下任何InvalidOperationException,直到SplashScreen消失。
为此,我在MyApplication类中添加了一个Property MainFormLoadingComplete
,在我的主窗体的Shown Event中设置为true(启动画面一直保持到处理Form_Load事件为止)。
我还想到我必须在MinimumSplashScreenDisplayTime
之前设置OnInitialize()
才能生效。希望这有助于首先避免异常。但是因为这个例外是完全随机的我
SplashScreen代码:
Public Class SplashScreen
Private Sub SplashScreen_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
' Simulate InvalidOperationException
Throw New InvalidOperationException
End Sub
End Class
Form1代码:
Public Class Form1
Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
My.MyApplication.MainFormLoadingComplete = True
End Sub
End Class
MyApplication代码:
Partial Friend Class MyApplication
Public Shared Property MainFormLoadingComplete As Boolean
Protected Overrides Function OnInitialize(ByVal commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean
' MinimumSplashScreenDisplayTime has to be set before OnInitialize to be effective
MinimumSplashScreenDisplayTime = 3000
Return MyBase.OnInitialize(commandLineArgs)
End Function
Private Sub MyApplication_Startup( _
ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
' Simulate application init process
System.Threading.Thread.Sleep(5000)
End Sub
Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
' Swallow InvalidOperationException if the MainForm has not been shown
If MainFormLoadingComplete = False AndAlso IsCausedByHideSplashScreen(e.Exception) Then
' Logging stuff...
' Prevent application exit
e.ExitApplication = False
End If
End Sub
Private Function IsCausedByHideSplashScreen(ByVal ex As Exception) As Boolean
If ex.GetType Is GetType(InvalidOperationException) Then
Return New StackTrace(ex).GetFrames().Count(Function(x) x.GetMethod().Name = "HideSplashScreen") > 0
Else
Return False
End If
End Function
End Class
答案 3 :(得分:-1)
刚刚遇到这个问题,我们使用相同的技术会遇到完全相同的问题。
我将尝试您的解决方案,但我只是想让您知道如何重现它:
我们的支持人员花了很多时间在这上面,最后将其缩小到仅在Windows 7中发生,并且仅在Windows启动后才发生。
如果您重新启动Windows,请立即启动使用此启动画面技术的应用程序,错误几乎会一直发生。
如果您重新启动Windows,请等待几分钟然后启动您的应用程序,您将永远不会看到错误。
我通过在主窗体的加载事件的底部进入睡眠状态(400)来解决它,但有些人仍然看到错误,我将尝试使用您的解决方案。