关闭时C#GUI处理问题

时间:2009-04-18 02:12:04

标签: c# multithreading user-interface

在搜索完成之前关闭我的应用程序时出现System.InvalidOperationException错误。当我关闭Form1_FormClosing时,我告诉我所有的线程都要中止。在一个线程中,它具有finalize,它调用委托函数,该函数告诉表单中的一个控件更改其文本。当发生这种情况时,我得到上面的例外以及“附加信息:在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。”

我该怎么做才能纠正这个问题?我可以添加一个isClosing标志并在更新文本之前检查它,但这感觉就像一个黑客并掩盖了问题。我该如何正确解决这个问题?

2 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为托管控件正在处理并且不再有其处理,但您还没有关闭窗口,所以您仍然可以看到它。

您可以创建一个包含Invoke调用的函数,并在调用IsHandleCreated之前检查Invoke。如果IsHandleCreated为false,则无法拨打Invoke,您可以忽略该来电。

public static class ControlExtensions
{
  public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                          Func<TControl, TResult> func)
    where TControl : Control
  {
    if (!control.IsHandleCreated)
      return default(T);

    if (control.InvokeRequired)
      return (TResult)control.Invoke(func, control);
    else
      return func(control);
  }

  public static void InvokeEx<TControl>(this TControl control,
                                        Action<TControl> action)
    where TControl : Control
  {
    control.InvokeEx(c => { action(c); return c; });
  }
}

所以现在只需用Invoke从你的线程中包装任何InvokeEx,它将处理控件何时被处理并且不再有句柄。

this.InvokeEx(c => c.label1.Text = "Hello world");

答案 1 :(得分:1)

我同意Samuel,但也会检查IsDisposed

void Handler()
{
  if (ctrl.IsDisposed || !ctrl.IsHandleCreated) return;
  if (ctrl.InvokeRequired) 
    Invoke(...);
  else {
    ...
  }
}