首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IsHandleCreated和InvokeRequired的顺序

IsHandleCreated和InvokeRequired的顺序
EN

Stack Overflow用户
提问于 2013-04-30 20:59:46
回答 2查看 5.7K关注 0票数 3

我有以下代码,我见过它以两种不同的方式编写。我只是好奇这两种方法中哪一种更好:

代码语言:javascript
复制
if (this.IsDisposed) return;

if (this.IsHandleCreated)
{
    if (this.InvokeRequired)
    {
        this.Invoke(action);
    }
    else
    {
        action();
    }
}

log.Error("Control handle was not created, therefore associated action was not executed.");

代码语言:javascript
复制
if (this.InvokeRequired)
{
    this.Invoke(action);
}
else    
{
    if (this.IsDisposed) return;

    if (!this.IsHandleCreated)
    {
         log.Error("Control handle was not created, therefore associated action was not executed.");
         return;
    } 

    action();
}

我最关心的是由需要有句柄的控件的操作引起的问题,而这些都不是显式必要的。如果我要做这样的事情,似乎可以通过确保控件在执行操作之前有一个句柄来解决我的问题。有什么想法?

代码语言:javascript
复制
if (control.InvokeRequired)
{
     control.Invoke(action);
}
else
{
    if (control.IsDisposed) return;

    if (!control.IsHandleCreated)
    {
        // Force a handle to be created to prevent any issues.
        log.Debug("Forcing a new handle to be created before invoking action.");
        var handle = control.Handle;
    }

    action();
}
EN

回答 2

Stack Overflow用户

发布于 2013-04-30 21:39:43

在检查InvokeRequired之前,您应该始终同时检查IsDisposedIsHandleCreated。这是一个令人抓狂的场景,我花了很多时间来掌握它。

以下是控件可能处于的状态:

  • New:控件存在,但其句柄尚未创建。在本例中,使用IsDisposed == falseIsHandleCreated == false,但使用InvokeRequired == false ,无论您使用哪个线程将其称为。如果您信任InvokeRequired的结果,而没有测试(或以其他方式知道)句柄是否已创建以及控件是否已被释放,则可能会意外地导致创建的句柄与错误的线程相关联,从而导致应用程序崩溃。(update)只有当控件是(或者是它的子控件)其句柄未被创建的窗体时,该状态才真正适用。该控件存在,它的句柄已被创建。这是一个简单的场景,没有什么奇怪的it.
  • Disposed:这是类似于上面的“新建”状态,但IsDisposed == true。再一次,InvokeRequired会对你撒谎,给你带来痛苦。

正确的方法应该是:

代码语言:javascript
复制
if(control.IsDisposed || (!control.IsHandleCreated && !control.FindForm().IsHandleCreated))
{
    // some exceptional condition:
    // handle in whatever way is appropriate for your app
    return;
}

if(control.InvokeRequired)
{
    control.Invoke(action);
}
else
{
    action();
}

附加说明

在.Net 2.0 (和3.x)中,这一点要糟糕得多。InvokeRequired现在将遍历控件层次结构,以确定是否已创建任何祖先控件的句柄,并验证它是在哪个线程上创建的。但是,如果控件位于从未显示过的窗体上,则也存在同样的危险。以前(在2.0 -3.5中),InvokeRequired没有遍历控制层次结构,导致更多的灾难机会。

票数 12
EN

Stack Overflow用户

发布于 2013-04-30 21:34:51

这并没有真正的区别。第二种方法的效率可能会稍微高一些,因为它只在InvokeRequired == false时调用IsHandleCreated。只有在创建句柄时,InvokeRequired才能为true,所以在这种情况下不需要调用IsHandleCreated

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16300527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档