下面的代码用于触发调用(减少了代码,为了更清楚起见,我省略了本例中的错误处理)
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方法创建一个新元素(不是只有一个字符串和一个带有字符串和布尔值的结构)。只能在UpdateSomething()方法中访问该元素。layOutControlGroup是Frm2的成员。
因此,在我看来,只有应该在Frm2线程中创建的新控件才应该附加到Frm2特定控件。
那么为什么它会坚持在FrmMain中呢?(主窗体,它调用窗体的方法来通知项的更新)
P.S. this.InvokeIfRequired <-这实际上是Frm2 ...
发布于 2013-06-06 20:03:45
因此,正如我们所看到的,( begin) invoke总是有问题。请改用BeginInvoke。是我的提示。通常它会说,控件上的begin invoke在创建句柄的同一线程中执行方法。
但是看起来,form2的句柄不是在同一线程中创建的,或者它可能还不存在。请试着检查并验证这一点。
阿。顺便说一句,在visual studio中,当异常被抛出时,标记它们。这有助于发现错误。
发布于 2013-06-06 20:32:04
我认为你用错误的控件检查了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);
}
}
https://stackoverflow.com/questions/16961404
复制相似问题