我得到了以下抛出的异常:
在创建窗口句柄之前,无法对控件调用Invoke或BeginInvoke。
这是我的代码:
if (InvokeRequired)
{
BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
}
else
Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
我在这个网站上找到了关于这个主题的页面,但我不知道出了什么问题。
8条答案
按热度按时间kx1ctssn1#
Invoke和BeginInvoke之间的区别在于前者是同步的(等待完成),而后者是异步的(类似于触发和遗忘)。然而,两者都是通过将消息发布到UI消息循环来工作的,这将导致委托在到达该消息时被执行。
InvokeRequired属性确定您是否需要Invoke,或者它是否已经在正确的线程上,而不是您想要同步调用还是异步调用。如果InvokeRequired为false,则(理论上)已经在UI线程上运行,可以直接执行同步操作(如果需要异步触发它们,则仍然使用BeginInvoke)。这也意味着如果InvokeRequired为false,则不能使用Invoke,因为当前线程上的消息循环无法继续。这是上面代码的一个大问题,但不一定是您报告的错误。如果您注意递归调用等,您 * 可以 * 实际上在任何情况下使用BeginInvoke。
但是,没有窗口句柄就不能使用其中任何一个。如果窗体/控件已经示例化但尚未初始化(即在它第一次显示之前)它可能还没有句柄。并且句柄被Dispose清除(),例如在窗体关闭之后。在这两种情况下,InvokeRequired都将返回false,因为没有句柄就无法调用。您可以选中IsDisposed、还有一个属性IsHandleCreated,它更具体地测试句柄是否存在。通常,如果IsDisposed为真(或IsHandleCreated为假),您希望插入一个特殊情况,例如简单地将操作丢弃为不适用。
因此,您需要的代码可能更像是:
或者:
tez616oj2#
这种情况通常发生在多线程场景中,在该场景中,一些外部源(可能是NetworkStream)在窗体正确初始化之前将数据推送到窗体。
该消息也可以在释放窗体后显示。
您可以检查
IsHandleCreated
以查看是否已经创建了表单,但是您需要将所有内容置于适当的错误处理中,因为如果您试图在应用程序关闭时更新表单,Invoke
语句可能会引发异常。vltsax253#
这是我答案
假设你想把"Hello World"写进一个文本框,那么如果你使用"Ishandlecreated",那么你的操作将不会发生,如果处理程序还没有创建,那么你必须强迫它自己创建处理程序。
下面是我的代码
gv8xihay4#
假设表单没有被释放,但还没有完全初始化,只需将
var X = this.Handle;
放在if
语句之前......this
表示相应表单的示例。参见http://msdn.microsoft.com/en-us/library/system.windows.forms.control.handle.aspx。
yhxst69z5#
如果在显示控件或对控件执行其他操作之前要使用来自另一个线程的控件,请考虑在构造函数中强制创建其句柄。这可以使用CreateHandle函数来完成。在多线程项目中,“控制器”逻辑不在WinForm中,此函数有助于避免此类错误。
myss37ts6#
这个怎么样
像这样使用它:
xpcnnkqh7#
您可能是在窗体的构造函数中调用此函数,此时基础系统窗口句柄尚不存在。
inn6fuwd8#
在调用invoke方法之前添加以下内容:
这个解决方案对我很有效。