Form.Focus InvalidOperationException:跨线程操作无效

时间:2016-05-20 15:45:38

标签: c# excel winforms .net-4.5

我在这里清楚地检查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);

1 个答案:

答案 0 :(得分:-1)

这种情况下的解决方案是Focus()方法不对表单本身起作用,而是由表单显示的主控件。当表单由于Application.Run调用而具有自己的单元状态时,其InvokeRequired与其主要控件无关。

所以解决方案是:

if (form.Controls[0].InvokeRequired)
{
    form.Controls[0].BeginInvoke((Action)(() => ...));
    return;
}
form.Focus();