在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke

我抛出以下exception:

在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。

这是我的代码:

if (InvokeRequired) { BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); } else Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); 

我在这个网站上找到了关于这个主题的网页,但我不知道出了什么问题。

Invoke和BeginInvoke之间的区别在于前者是同步的(等待完成),而后者是异步的(类似于“忘掉”)。 但是,两者都通过向UI消息循环发布消息来工作,这将导致委托在到达该消息时被执行。

InvokeRequired属性确定您是否需要完全调用或者是否已经在正确的线程上,而不是您是否需要同步或异步调用。 如果InvokeRequired为false,您(理论上)已经在UI线程上运行,并且可以直接执行同步操作(或者如果需要异步触发它们,则仍然是BeginInvoke)。 这也意味着如果InvokeRequired为false,则无法使用Invoke,因为当前线程上的消息循环无法继续。 这是上面代码的一个大问题,但不一定是您报告的错误。 如果你注意递归调用,你实际上可以在任何一种情况下使用BeginInvoke,依此类推。

但是,如果没有窗口句柄,则不能使用任何一个。 如果Form / Control已经实例化但未初始化(即,在首次显示之前),它可能还没有句柄。 并且Dispose()会清除句柄,例如在Form关闭后。 在任何一种情况下,InvokeRequired都将返回false,因为没有句柄就无法调用。 您可以检查IsDisposed,并且还有一个属性IsHandleCreated,它更具体地测试句柄是否存在。 通常情况下,如果IsDisposed为真(或者如果IsHandleCreated为false),您想要进入一个特殊情况,例如简单地将操作丢弃为不适用。

所以,你想要的代码可能更像是:

 if (IsHandleCreated) { // Always asynchronous, even on the UI thread already. (Don't let it loop back here!) BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); return; // Fired-off asynchronously; let the current thread continue. // WriteToForm will be called on the UI thread at some point in the near future. } else { // Handle the error case, or do nothing. } 

或者可能:

 if (IsHandleCreated) { // Always synchronous. (But you must watch out for cross-threading deadlocks!) if (InvokeRequired) Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); else WriteToForm(finished, numCount); // Call the method (or delegate) directly. // Execution continues from here only once WriteToForm has completed and returned. } else { // Handle the error case, or do nothing. } 

这通常发生在multithreading场景中,其中一些外部源(可能是NetworkStream)在表单正确初始化之前将数据推送到表单。

处理表单后也可以显示该消息。

您可以检查IsHandleCreated以查看是否已创建表单,但是您需要将所有内容置于正确的error handling中,因为如果您尝试在应用程序关闭时更新表单,则Invoke语句可能会引发exception。

这是我的答案

假设你想在文本框中写“Hello World”。 然后,如果您使用“Ishandlecreated”,那么如果尚未创建处理程序,则不会执行您的操作。 因此,如果尚未创建,则必须强制自己使用CreateHandlers。

这是我的代码

 if (!IsHandleCreated) this.CreateControl(); this.Invoke((MethodInvoker)delegate { cmbEmail.Text = null; }); 

如果您要在显示控件或使用控件执行其他操作之前使用其他线程中的控件,请考虑在构造函数中强制创建其句柄。 这是使用CreateHandle函数完成的。 在multithreading项目中,“控制器”逻辑不在WinForm中,此function有助于避免这些类型的错误。

假设表格没有处理但尚未完全初始化,只需将var X = this.Handle; 在那之前, if声明…… this表示相应forms的实例。

请参阅http://msdn.microsoft.com/en-us/library/system.windows.forms.control.handle.aspx 。

您可能在窗体的构造函数中调用它,此时底层系统窗口句柄尚不存在。