调用或BeginInvoke异常 [英] Invoke or BeginInvoke Exception

查看:130
本文介绍了调用或BeginInvoke异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用vb.net编写的Windows窗体应用程序.我有一个名为SplashScreen的表单,该表单在项目属性中设置为Splash屏幕.启动窗体设置为称为登录的窗体.我有一个用户在运行我的应用程序时出现异常.它发生在显示初始屏幕之后和登录屏幕显示之前.用户再次尝试,没有再次得到该错误.但是,如果任何人有任何想法会导致此问题,那么我可以确保它已解决,我将不胜感激.

谷歌搜索此错误时,似乎可能与线程有关,但我在登录屏幕上没有做任何特别的事情,接受使用Me.Activate().启动画面消失后,登录画面没有聚焦,我遇到了麻烦,发现某个论坛说Me.Activate()可以解决该问题,并且它可以解决.

I have a windows forms application written in vb.net. I have a form called SplashScreen which is set as the Splash screen in the project properties. The Startup form is set to a form called Logon. I have a user who got an exception when running my app. It occurred right after the splash screen displayed and right before the logon screen displays. The user tried again and hasn''t gotten the error again. However, if anyone has any ideas what could be causing this so I can make sure it''s fixed, I''d appreciate it.

When googling this error, it seems that it may be related to threading, but I don''t do anything special on my logon screen accept use a Me.Activate(). I was having trouble with the logon screen not having focus after the splash screen disappeared and found some forum that said Me.Activate() would fix it, and it has.

Private Sub Logon_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'This statement will fix the issue users occasionaly have with the logon form not having focus after the splash screen goes away
        Me.Activate()
        'Other loading tasks...
End Sub


这是错误消息:


Here is the error message:

Message: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
Exception: 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)
Stack Trace:    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)


有人有什么想法会导致这种情况吗?

****更新****
我的一位用户继续随机出现此错误.和以前一样,他将尝试运行该应用程序,获取错误,然后在几秒钟后尝试再次运行该应用程序,并且一切正常.我尝试将Me.Activate()代码移至Logon_Shown事件.用户仍然每隔一段时间仍会收到该错误.然后尝试完全删除Me.Activate().用户仍会收到错误.当我发布该应用程序的新版本并且用户尝试首次运行它时,似乎会发生这种情况.但是它在其他时间也随机发生.可能在用户重新启动之后,但不是在每次重新启动之后.他使用的是运行Windows 7的计算机,该计算机具有管理员权限,并且UAC级别处于最高级别,但没有.这个用户发生了足够多的事情,我担心我需要更改某些内容或修复某些问题,但是再次……我不知道从哪里开始.内置的启动画面功能似乎是一个问题.如果有人有任何新建议,我将不胜感激.


Does anyone have any ideas what would cause this?

**** UPDATE ****
One of my users continues to get this error randomly. Just like before, he''ll try to run the app, get the error, then try to run the app again a few seconds later and it works just fine. I tried moving the Me.Activate() code to the Logon_Shown event. The user still gets the error every once and a while. Then tried removing the Me.Activate() entirely. The user STILL gets the error. It seems to happen when I publish a new version of the application and the user tries to run it for the first time. But it has also happened randomly at other times. Possibly after the user has rebooted, but not every time he reboots. He uses a machine that runs Windows 7, has admin authority, and has the UAC stuff on but not at it''s highest level. It''s happened enough with this user that I''m concerned I need to change something or fix something, but again...I have no idea where to start. It appears to be an issue with the built in splash screen feature. If anyone has any new suggestions, I would appreciate any ideas.

推荐答案

这似乎意味着您试图与尚不存在的表单元素进行交互.查看您的构造函数,并询问是否有更好的东西转移到Load事件.
This looks like it means you tried to interact with a form element that did not exist yet. Look at your constructors and ask if there''s stuff better moved to the Load event.


我们可以用这种方式重现该错误.

重新引导计算机,并在操作系统加载后立即启动应用程序.如果几乎总是会触发您提到的未处理的异常!如果在操作系统加载后几分钟将其保留,则可能不会收到异常.

该错误似乎仅在Windows 7中发生.

此修复程序对我有用.

在My.Settings中添加一个布尔值(LoadFinished)

将以下内容添加到ApplicationEvents

We can reproduce the error this way.

Re-boot the machine and as soon as the OS has loaded start you application. If will almost always fire the unhandled exception you mentioned! If you leave it a few minutes after the OS has loaded you might not get the exception.

The error only seems to happen with Windows 7.

This fix worked of me.

Add a boolean in My.Settings (LoadFinished)

Add the following to ApplicationEvents

'Engineering case 220125 -  'Invoke or BeginInvoke cannot be called on a control until the window handle has beeen created.'
        Private Sub MyApplication_Startup(sender As Object, e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
            Try
                If Not Me.SplashScreen Is Nothing Then
                    While My.Settings.LoadFinished = False
                        System.Threading.Thread.Sleep(5000)
                    End While
                End If
                My.Settings.LoadFinished = False
            Catch ex As Exception
                EmailError(ex)
            End Try
        End Sub

        Protected Overrides Function OnInitialize(commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean
            MinimumSplashScreenDisplayTime = 3000
            Return MyBase.OnInitialize(commandLineArgs)
        End Function



将此添加到您的启动屏幕加载事件中(在最后)



Add this to your splash screen load event (at the very end)

My.Settings.LoadFinished = True


哦,我可以看到错误.

首先,让我向您保证,您有一个窗体构造函数.只要找到它.看来您正在处理假"事件Form.Load.在自动生成的布局调用之后,实际上会触发此事件,就像您将其处理程序放置在构造函数中一样.我实际上是手动执行的,从不使用此事件.这不是问题.

问题是您呼叫Activate.当然早了!

在构造函数中,尚未创建窗口本身的Windows句柄,请忘记其他控件.在那里无法完成许多操作.要真正确定调用还为时不晚,请在事件Form.Shown的句柄中或在重写的虚拟方法Form.OnShown中进行.

请参阅:
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx [ ^ ],
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onshown.aspx [ ^ ].

但是,通常您根本不需要调用Activate.通常,表单是由其自身激活的.您有时需要激活它,但不是在创建时激活它,而是在其他某种形式处于活动状态并且想要激活另一种形式时.



回应后续讨论:

请参阅我最近讨论类似情况的答案:
在vb.net中关闭子表单 [ ^ ].

也许您执行类似的方法:需要先显示一种形式:启动然后显示主形式,但是您可能以错误的方式进行.

—SA
Oh, I can see the bug.

First of all, let me assure you that you have a form constructor. Just find it. It looks like you are handling the "fake" event Form.Load. This event is actually fired as if your place its handler in a constructor, after the auto-generated layout call. I actually do it manually, never use this event. This is not a problem yet.

The problem is that you call Activate. Of course it''s way to early!

In the constructors the Windows handle for the window itself is not yet created, forget other controls. Many operations cannot be done there. To be really sure you call is not too late, do it in the handle of the event Form.Shown or in the overridden virtual method Form.OnShown.

Please see:
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onshown.aspx[^].

However, usually you don''t need to call Activate at all. Normally, the form is activated by itself. You need to activate it sometimes, but not when it is created, but when some other form is active and you want to activate another one.



In reply to follow-up discussion:

Please see my recent answer where similar situation was discussed:
Close child form in vb.net[^].

Perhaps you do similar way: need to show one form after another: splash and then the main form, but you might do it in a wrong way.

—SA


这篇关于调用或BeginInvoke异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆