关闭Form(线程+调用)时出现异常

时间:2013-10-27 15:46:06

标签: c# multithreading exception

我刚开始学习c#中的线程和方法,但我遇到了一个我找不到解决方案的问题。

我制作了一个基本的C#表单程序,通过启动一个线程并调用委托来不断更新和显示一个数字。

在Form1_load上启动新线程:

private void Form1_Load(object sender, EventArgs e)
  {
        t = new System.Threading.Thread(DoThisAllTheTime);
        t.Start();
  }

Public void DoThisAllTheTime(不断更新数字):

public void DoThisAllTheTime()
  {
     while(true)
      {
        if (!this.IsDisposed)
         {
           number += 1;
           MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
           this.Invoke(yolo);
         }
      }
  }

现在,当我单击表单的X按钮时,出现以下异常:

'System.Windows.Forms.dll中发生了'System.ObjectDisposedException'类型的未处理异常

无法更新已删除的对象'

虽然我确实检查了表格是否已被处理。

编辑:我在修复问题的代码中添加了catch(ObjectDisposedException ex)。 工作代码:

  public void DoThisAllTheTime()
  {
     while(true)
      {
         number += 1;

         try {  
              MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
              this.Invoke(yolo);
             }
         catch (ObjectDisposedException ex)
             {
              t.Abort();
             }
      }
 }

3 个答案:

答案 0 :(得分:3)

您对this.IsDisposed的来电总是过时的。您需要拦截表单结束事件并明确停止该线程。那么你根本不需要进行IsDisposed测试。

有很多方法可以做到这一点。就个人而言,我会使用System.Threading.Tasks命名空间,但是如果你想继续使用System.Threading,你应该定义一个成员变量_updateThread,并在你的load事件中启动它:

_updateThread = new System.Threading.Thread(DoThisAllTheTime);
_updateThread.Start();

然后在你的结束活动中:

private void Form1_Closing(object sender, CancelEventArgs e)
{
    _stopCounting = true;
    _updateThread.Join();
}

最后,替换IsDisposed测试并检查新_stopCounting成员变量的值:

public void DoThisAllTheTime()
{
    MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
    while(!_stopCounting)
    {
        number += 1;
        this.Invoke(yolo);
    }
}

答案 1 :(得分:2)

只需将此覆盖放在表单类中:

protected override void OnClosing(CancelEventArgs e) {
    t.Abort();
    base.OnClosing(e);
}

答案 2 :(得分:-3)

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Thread.CurrentThread.Abort();
}