【问题标题】:C# GUI handle problems on closeC# GUI 处理关闭时的问题
【发布时间】:2009-04-18 02:12:03
【问题描述】:

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

我能做些什么来纠正这个问题?我可以添加一个 isClosing 标志并在更新文本之前对其进行检查,但这感觉就像是一种黑客攻击并掩盖了问题。我该如何正确解决这个问题?

【问题讨论】:

    标签: c# multithreading user-interface


    【解决方案1】:

    发生这种情况是因为托管控件正在被释放并且不再具有其句柄,但您尚未关闭窗口,因此您仍然可以看到它。

    您可以创建一个函数来包装Invoke 调用,并在调用Invoke 之前检查IsHandleCreated。如果IsHandleCreated 为假,则不能调用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; });
      }
    }
    

    因此,现在只需使用 InvokeEx 将线程中的任何 Invokes 包装起来,它就会在控件已被释放且不再具有句柄时进行处理。

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

    【讨论】:

      【解决方案2】:

      我同意 Samuel 的观点,但也会检查 IsDisposed

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 2012-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-10
        • 1970-01-01
        相关资源
        最近更新 更多