调用或BeginInvoke可直到窗口句柄已创建不能在一个控件调用 [英] Invoke or BeginInvoke cannot be called on a control until the window handle has been created

查看:192
本文介绍了调用或BeginInvoke可直到窗口句柄已创建不能在一个控件调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到下面的异常抛出:

I get the following exception thrown:

调用或BeginInvoke可直到窗口句柄已创建不能在控制名为

Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

这是我的代码:

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



我发现关于这个网站主题相关的网页,但我不知道什么是错。

I found pages about this topic on this site but I don't know what is wrong.

推荐答案

调用和BeginInvoke的之间的差别在于,前者是同步的(对于完成等待),而后面是异步(排序的防火和忘记了)。然而,当它到达该消息将被执行通过发布消息到UI消息循环都工作,这将导致该委托。

The difference between Invoke and BeginInvoke is that the former is synchronous (waits for completion) while the later is asynchronous (sort of fire-and-forget). However, both work by posting a message to the UI message loop which will cause the delegate to be executed when it gets to that message.

InvokeRequired属性决定是否需要在所有调用,或者如果它已经在正确的线程,而不是您是否要同步或异步调用。如果InvokeRequired是假的,你是(理论上)在UI线程上已经运行,并可以干脆直接执行同步操作(或静止的BeginInvoke如果您需要解雇他们了异步)。这也意味着你不能使用调用如果InvokeRequired是假的,因为没有办法在当前线程上的消息循环继续。所以这是一个大问题,上面的代码,但不一定是错误您报告。您的可以的居然在这两种情况下使用的BeginInvoke,如果你注意递归调用,等等。

The InvokeRequired property determines whether you need to Invoke at all or if it is already on the correct thread, not whether you want synchronous or asynchronous calling. If InvokeRequired is false you are (in theory) already running on the UI thread and can simply perform synchronous actions directly (or still BeginInvoke if you need to fire them off asynchronously). This also means you can't use Invoke if InvokeRequired is false, because there's no way for the message loop on the current thread to continue. So that's one big problem with your code above, but not necessarily the error you're reporting. You can actually use BeginInvoke in either case, if you watch out for recursive invocation, and so on.

不过,您不能使用任何一个没有窗口句柄。如果窗体/控件被实例化但尚未初始化(即首次上映之前),可能没有一个手柄呢。而手柄得到由Dispose()方法清除,如窗体关闭后。在这两种情况下InvokeRequired将返回false因为它不可能在无句柄调用。可以检查IsDisposed,并且也有如果手柄存在哪个更具体测试一个属性IsHandleCreated。通常,如果IsDisposed为真(或者,如果IsHandleCreated是假的),你想踢成一种特殊情况,如简单地下探的动作为不适用。

However, you can't use either one without a window handle. If the Form/Control has been instantiated but not initialized (ie. before it is first shown) it may not have a handle yet. And the handle gets cleared by Dispose(), such as after the Form is closed. In either case InvokeRequired will return false because it is not possible to invoke without a handle. You can check IsDisposed, and there is also a property IsHandleCreated which more specifically tests if the handle exists. Usually, if IsDisposed is true (or if IsHandleCreated is false) you want to punt into a special case such as simply dropping the action as not applicable.

所以,代码你想大概是更喜欢:

So, the code you want is probably more like:

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.
}



也许

Or maybe:

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.
}

这篇关于调用或BeginInvoke可直到窗口句柄已创建不能在一个控件调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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