1

次のコードは、呼び出しをトリガーするために使用されます (コードは削減されています。この例では、より明確にするためにエラー処理を省略しています)

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 を含む構造体のみがあります)。この要素は、UpdateSomething() メソッド内でのみアクセスされます。layOutControlGroup は Frm2 のメンバーです。

したがって、私の意見では、Frm2 スレッドで作成する必要がある新しいコントロールのみを、Frm2 固有のコントロールに接続する必要があります。

では、なぜ FrmMain を主張するのでしょうか。(アイテムの更新を通知するためにフォームのメソッドを呼び出すメイン フォーム)

PS this.InvokeIfRequired <-これは実際にはFrm2です...

4

2 に答える 2

0

I think that you checked InvokeRequired with a wrong control.

What you needed to check with InvokeRequired is layoutControlGroup, but your extension method checks on form's with the code this.InvokeIfNecessary where this is Frm2.

Also, you invoked layoutControlGroup.BeginUpdate() but layoutControlGroupCA.EndUpdate(), seems not symmetric of the usage.

A correction of the code might be:

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);
    }
}
于 2013-06-06T12:32:03.910 に答える