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