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?(主表单,它调用表单的方法来通知项的更新)
注:这一点。
所以,正如我们所看到的,(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);
}
}