InvalideOperationException / invoke

点点圈 提交于 2019-12-24 07:07:50

问题


the following code is used to trigger invoke (code is reduced, i left out the error handling in this example to make it more clear)

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

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

Normally it works fine, but sometimes if i call a method of a Form an InvalidOperationException is given. Schematic method to be called

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

Well... I must admit that i have a conceptual problem here.

Why is the Exception thrown here?

The Frm2 method creates a new element (In NO there is only a string and a struct with strings and bool). The element is only accessed within the UpdateSomething() method. The layOutControlGroup is a member of Frm2.

So in my opinion only a new Control which shoudl be created in Frm2 Thread should be attached to a Frm2 specific Control.

So why does it insisting in FrmMain? (the main form, which calls the method of the form to inform about an update of items)

P.S. this.InvokeIfRequired <- this is Frm2 actually...


回答1:


So, as we see, there are always trouble with ( begin) invoke. Use BeginInvoke instead. is my hint. Usually it says, that begin invoke on controls executes a method in the same thread where the handle was created on.

But as it seems, the handle of form2 is not been created in the same thread, OR perhaps it is not present yet. Try to check this and verify this, please.

Ah. by the way, flag exceptions, clr, in visual studio, when they are thrown. This helps to spot the error.




回答2:


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


来源:https://stackoverflow.com/questions/16961404/invalideoperationexception-invoke

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!