我在这里清楚地检查InvokeRequired
,但是返回false,然后是抛出InvalidOperationException的表单。我做错了什么?
/// <summary>Position the specified form within the specified bounds,
/// and focus it, all in a thread-safe manner.</summary>
private static void FocusForm_Helper(Form form, double top, double height, double left, double width)
{
if (form?.IsDisposed ?? true)
return;
if (form.InvokeRequired)
{
form.Invoke((Action)(() => FocusForm_Helper(form, top, height, left, width)));
return;
}
form.Top = (int)(top + 0.5 * (height /*- form.Height*/));
form.Left = (int)(left + 0.5 * (width /*- form.Width*/));
form.Focus();
}
System.InvalidOperationException:跨线程操作无效: 控制'DataUploadDialog'从除以外的线程访问 线程是在它上面创建的。
在System.Windows.Forms.Control.get_Handle()处 System.Windows.Forms.Control.get_CanFocus()at System.Windows.Forms.Control.FocusInternal()at System.Windows.Forms.Control.Focus()at ExcelDNA.CustomRibbon.FocusForm_Helper(表格形式,双顶,双 高度,双左,双宽)
我在主线程上创建了这个控件,然后在一个单独的线程上运行它,以便它有自己的消息泵。然后我调用焦点在控件上,期望它在必要时检测InvokeRequired并在相应的线程上调用“Focus”,但它没有发生。
_launchedDataUploadDialog = new DataUploadDialog();
var thread = new Thread(() =>
{
try
{
System.Windows.Forms.Application.Run(_launchedDataUploadDialog);
}
catch (Exception ex)
{
MessageBox.Show("Data upload utility halted unexpectedly.\n\n" + ex);
_launchedDataUploadDialog = null;
}
});
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
FocusForm(_launchedDataUploadDialog);
答案 0 :(得分:-1)
这种情况下的解决方案是Focus()
方法不对表单本身起作用,而是由表单显示的主控件。当表单由于Application.Run
调用而具有自己的单元状态时,其InvokeRequired
与其主要控件无关。
所以解决方案是:
if (form.Controls[0].InvokeRequired)
{
form.Controls[0].BeginInvoke((Action)(() => ...));
return;
}
form.Focus();