我有一个场景,我必须将Form的实例称为ShowDialog()。 我的代码就像:
Form view = ComponentFactory.GetInstance<IView>
(viewConfig.Key) as Form;
if (view == null)
{
if (_sysLog.IsErrorEnabled)
_sysLog.Error("Invalid view configuration. Aborting!");
throw new AbstractModelException("View not found.");
}
if (isFixed)
view.FormBorderStyle = FormBorderStyle.FixedDialog;
view.StartPosition = FormStartPosition.CenterScreen;
view.ShowInTaskbar = false;
view.FormClosed += new FormClosedEventHandler(OnViewClosed);
view.FormClosing += new FormClosingEventHandler(OnViewClosing);
if (view is IView)
{
InitializeView((IView)view);
((IView)view).Tag = tag;
}
if (parentWindow != null && parentWindow is IWin32Window)
return view.ShowDialog(parentWindow as IWin32Window);
return view.ShowDialog();
我已将.net 3.5中的引用转换为4.0。
Error is:
Cross-thread operation not valid: Control '' accessed from a thread other than the
thread it was created on.
这表示表单控件已经在UI线程中运行。
我试图通过
来解决它 if(view.InvokeRequired)
{
MethodInvoker method = new MethodInvoker(() => view.ShowDialog());
DialogResult result = (DialogResult)view.Invoke(method);
}
我尝试了Invoke和BeginInvoke
两者。每次InvokeRequired在这里都是假的。
我也试过打电话给view.CreateControl
,因为有些地方我读过的可能是
尚未创建表单控件,并且不会创建表单句柄。
但这也行不通。
每当ShowDialog
响应返回时出现错误。通过ShowDialog这个
打开表单并在表单关闭后处理后返回a
的DialogResult。之后,这将返回到调用当前函数的另一个类。
请指导。
答案 0 :(得分:2)
根据MSDN InvokeRequired
即使在false
应为InvokeRequired
的情况下也可以返回true
- 即在您访问InvokeRequired
的情况下在创建该控件/表单(或其父项)的Handle
之前。
基本上,您的支票不完整会导致您看到的结果。
您需要检查IsHandleCreated
- 如果是false
,那么无论Invoke
返回什么,您都需要使用BeginInvoke
/ InvokeRequired
。
<强> BUT 强>:
由于Invoke
/ BeginInvoke
检查哪个线程创建了Handle
来实现他们的魔法,这通常无法有效运行...
只有当IsHandleCreated
为true
时,您才会根据InvokeRequired
返回的内容采取行动 - 以下内容:
if (control.IsHandleCreated)
{
if (control.InvokeRequired)
{
control.BeginInvoke(action);
}
else
{
action.Invoke();
}
}
else
{
// in this case InvokeRequired might lie - you need to make sure that this never happens!
throw new Exception ( "Somehow Handle has not yet been created on the UI thread!" );
}
因此,以下内容对于避免此问题很重要
始终确保在第一次访问UI线程以外的线程之前已创建Handle
。
根据MSDN,您只需要在UI线程中引用control.Handle
以强制创建它 - 在您的代码中,这必须在您第一次从任何线程访问该控件/表单之前发生那不是UI线程。