订购IsHandleCreated和InvokeRequired的IsHandleCreated、InvokeRequired

2023-09-04 05:57:44 作者:朕不想活了

我有以下的code,我已经看到它写两种不同的方式。我只是好奇,这两种方式是更好的做法是:

 如果(this.IsDisposed)回报;

如果(this.IsHandleCreated)
{
    如果(this.InvokeRequired)
    {
        this.Invoke(动作);
    }
    其他
    {
        行动();
    }
}

(未创建,不被执行,因此相关的动作控制手柄。)log.Error;
 

VS

 如果(this.InvokeRequired)
{
    this.Invoke(动作);
}
其他
{
    如果(this.IsDisposed)回报;

    如果(!this.IsHandleCreated)
    {
         (未创建,不被执行,因此相关的动作控制手柄。)log.Error;
         返回;
    }

    行动();
}
 

我最关心的是从需要控制有一个手柄行动所造成的问题,这些是它没有明确必要的。如果我做这样的事情,似乎通过确保执行行动前的控制将有一个手柄来解决我的问题。思考?

 如果(control.InvokeRequired)
{
     control.Invoke(动作);
}
其他
{
    如果(control.IsDisposed)回报;

    如果(!control.IsHandleCreated)
    {
        //强制手柄被创建到prevent任何问题。
        log.Debug(强制新的句柄调用操作之前被创建。);
        VAR手柄= control.Handle;
    }

    行动();
}
 
dedecms设置RSS订阅全站动态订阅更新文章的方法

解决方案

您应经常检查这两个 IsDisposed IsHandleCreated 前检查 InvokeRequired 。这是一个让人郁闷的情况,我已经花了很多时间掌握。

下面是该国的控制可能有:

新的:控制存在,但他的把柄尚未创建。在这种情况下, IsDisposed ==假 IsHandleCreated ==假,而 InvokeRequired ==假 无论什么线程用于调用它。如果您信任的 InvokeRequired 的结果,而测试(或知道一些其他的方式)是否手柄已经创建并控制是否已经被释放,有可能意外导致手柄获得创建相关的错误的线程,它会崩溃您的应用程序。 (更新)这种状态实际上只适用于如果控制(或者是一个孩子)的处理还没有被创建的窗体。 投放的:控制存在,将创建其句柄。这是最简单的情况下,没有什么奇怪的了。 处置的:这是类似新的状态上面,但 IsDisposed ==真。此外, InvokeRequired 会骗你,使你痛苦。

正确的方式做,这将是:

 如果(control.IsDisposed ||(control.IsHandleCreated&安培;!&安培;!control.FindForm()IsHandleCreated))
{
    //一些异常情况:
    //以任何方式处理是适合您的应用程序
    返回;
}

如果(control.InvokeRequired)
{
    control.Invoke(动作);
}
其他
{
    行动();
}
 

其他注意事项

在NET 2.0(和3.x)这次则是将更多。 InvokeRequired 现在走的控制层次结构,以确定是否有任何祖先控件的句柄已经建立,并且线程上创建它的验证。然而,如果控制是从未​​示出的表格上,同样的危险适用。 previously(2.0 - 3.5), InvokeRequired 没走的控制层次,从而为灾难更多的机会。

I have the following code, and I've seen it written two different ways. I'm just curious which of the two ways is better practice:

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.");

vs.

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();
}

I'm mostly concerned with issues stemming from actions that require a control have a handle, and those were it's not explicitly necessary. If I were to do something like this, it seems to solve my problems by ensuring that the control will have a handle before the action is executed. Thoughts?

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();
}

解决方案

You should always check both IsDisposed and IsHandleCreated before checking InvokeRequired. This is a maddening scenario that I've spent many hours mastering.

Here are the states that a control can be in:

New: the control exists, but his handle hasn't been created. In this case, IsDisposed == false, IsHandleCreated == false, but InvokeRequired == false no matter what thread you use to call it. If you trust the results of InvokeRequired without testing (or knowing some other way) whether the handle has been created and whether the control has been disposed, you could accidentally cause the handle to get created associated with the wrong thread, and it would crash your app. (update) This state really only applies if the control is (or is a child of) a form whose handle hasn't been created yet. Live: the control exists, its handle is created. This is the easy scenario, nothing strange about it. Disposed: this is similar to the "New" state above, but IsDisposed == true. Again, InvokeRequired will lie to you and cause you misery.

The right way to do this would be:

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();
}

Additional Notes

In .Net 2.0 (and 3.x) this sucked much more. InvokeRequired will now walk the control hierarchy to determine if any ancestor control's handle has been created, and validated which thread it was created on. However, if the control is on a form that has never been shown, the same dangers apply. Previously (in 2.0 - 3.5), InvokeRequired didn't walk the control hierarchy, leading to more opportunity for calamity.

 
精彩推荐
图片推荐