InvalideOperationException / invoke

本文关键字:invoke InvalideOperationException | 更新日期: 2023-09-27 18:17:07

下面的代码用于触发调用(代码减少了,为了更清楚,我省略了本例中的错误处理)

public static void InvokeIfNecessary(this Control control, MethodInvoker methodInvoker)
{
    if (control != null && !control.IsDisposed && !control.Disposing)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(methodInvoker);
        }
        else
        {
            methodInvoker();
        }
    }
}

通常它工作得很好,但有时如果我调用一个窗体的方法InvalidOperationException给出。要调用的原理图方法

// in a Frm2:
internal void UpdateSomething()
{
    List<NO> myObjects = frmMain.NO.GetNOs();
    if (null != myObjects)
    {
        this.InvokeIfNecessary(() =>
        {
            layoutControlGroup.BeginUpdate(); // DevExpress Layoutcontrolgroup
            foreach (NO aObject in myObjects)
            {
                if(...) // if already a control for the object exist update it.
                {
                    // update
                }
                else
                {
                    // add item
                    LayoutControlItem layoutControlItem = new LayoutControlItem();
                    // create new control
                    Control control = CreateNewControl(aObject);
                    layoutControlItem.Control = control;
                    // do some stuff with visibility and size of control
                    ...
                    layoutControlGroup.AddItem(layoutControlItem); // <-- And here the InvalidOperationException occurs.
                    /// The message is (translated
                    /// InvalidOperationException was not handled by usercode
                    /// The acces on the Control FrmMain was done from another Thrad then the thread which created it.
                    ...;
                }
            }

            ...;
            layoutControlGroupCA.EndUpdate();
        });
    }
}

嗯…我必须承认我在概念上有问题。

为什么在这里抛出异常?

Frm2方法创建一个新元素(在NO中只有一个字符串和一个带字符串和bool的结构体)。该元素只能在updatessomething()方法中访问。layOutControlGroup是Frm2的成员。

所以在我看来,只有一个应该在Frm2线程中创建的新控件应该附加到Frm2特定的控件。

那么为什么它坚持在FrmMain?(主表单,它调用表单的方法来通知项的更新)

注:这一点。

InvalideOperationException / invoke

所以,正如我们所看到的,(begin)调用总是有问题。使用BeginInvoke代替。这是我的提示。通常它说,begininvoke on controls在创建句柄的同一线程中执行一个方法。

但是看起来,form2的句柄不是在同一个线程中创建的,或者它可能还不存在。请检查并验证一下。

啊。顺便说一下,标记异常,clr,在visual studio中,当它们被抛出。这有助于发现错误。

我认为你用错误的控件检查InvokeRequired

你需要用InvokeRequired检查的是layoutControlGroup,但是你的扩展方法检查形式的代码this.InvokeIfNecessary,其中this是Frm2。

同样,你调用了layoutControlGroup.BeginUpdate(),但layoutControlGroupCA.EndUpdate(),似乎不对称的用法。

代码的更正可以是:

internal void UpdateSomething() {
    var myObjects=frmMain.NO.GetNOs();
    if(null!=myObjects) {
        MethodInvoker beginUpdate=() => layoutControlGroup.BeginUpdate();
        MethodInvoker endUpdate=() => layoutControlGroup.EndUpdate();
        layoutControlGroup.InvokeIfNecessary(beginUpdate);
        foreach(NO aObject in myObjects)
            if(SomeCondition) {
                // update
            }
            else {
                LayoutControlItem layoutControlItem=new LayoutControlItem();
                Control control=CreateNewControl(aObject);
                layoutControlItem.Control=control;
                MethodInvoker addItem=
                    () => {
                        layoutControlGroup.AddItem(layoutControlItem);
                    };
                layoutControlGroup.InvokeIfNecessary(addItem);
            }
        layoutControlGroup.InvokeIfNecessary(endUpdate);
    }
}