Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关闭表单时出现异常(线程调用)_C#_Multithreading_Exception - Fatal编程技术网

C# 关闭表单时出现异常(线程调用)

C# 关闭表单时出现异常(线程调用),c#,multithreading,exception,C#,Multithreading,Exception,我刚刚开始学习c#中的线程和方法调用,但我遇到了一个无法解决的问题 我制作了一个基本的C#form程序,通过启动一个线程并调用委托来不断更新和显示一个数字 在Form1_load上启动新线程: private void Form1_Load(object sender, EventArgs e) { t = new System.Threading.Thread(DoThisAllTheTime); t.Start(); } Public void始终显

我刚刚开始学习c#中的线程和方法调用,但我遇到了一个无法解决的问题

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

在Form1_load上启动新线程:

private void Form1_Load(object sender, EventArgs e)
  {
        t = new System.Threading.Thread(DoThisAllTheTime);
        t.Start();
  }
Public void始终显示此消息(该消息会不断更新号码):

现在,当我单击表单的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();
             }
      }
 }

您对
this.IsDisposed
的呼叫总是过期。您需要截获表单关闭事件并显式停止线程。这样你就根本不必做
IsDisposed
测试了

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

_updateThread = new System.Threading.Thread(DoThisAllTheTime);
_updateThread.Start();
然后在闭幕式上:

private void Form1_Closing(object sender, CancelEventArgs e)
{
    _stopCounting = true;
    _updateThread.Join();
}
最后,将
IsDisposed
测试替换为检查新
\u stopCounting
成员变量的值:

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

只需将此重写放在表单类中:

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

嗯,表单在计算
(!this.IsDisposed)
之后被处理,但在
this.Invoke(yolo)之前被处理已被调用。欢迎来到种族世界。我已经编辑了你的标题。请看,“,其中的共识是“不,他们不应该”。@Joker\u vD我该如何解决这个问题?我认为检查会比方法调用更快。它也以这种方式在MSDN上使用。()正如其他人已经说过的,这是一个种族问题,请参见:@Bart不要指望MSDN示例代码是正确的。通常不是。我尝试添加't.abort();'以形成1_关闭,但这也没有帮助。@巴特:尝试设置一个标志,然后调用
t.Join()等待线程识别它。我向它添加了catch(ObjectDisposedException ex)。这解决了问题。我会更新我的问题。@Bart:正如oefe所说的,那太可恶了!:由于
Invoke
正在阻塞等待主线程,如果在
number+=1行上执行
Form1\u Closing
方法,则此处可能出现死锁。随着越来越多的工作被取代,死锁的可能性也越来越大。我在我的应用程序中通过使用
BeginInvoke
而不是
Invoke
修复了这个问题,因为
BeginInvoke
不会阻止线程退出,因此
Join
不会永远被阻止。+1是一个很好的解决方案。欲了解更多信息,请访问@Alireza,谢谢,伙计。答案与我从这个问题中获得并思考的初学者技能是一致的。但真的谢谢你。异常场景关闭不能包括对
Thread.Abort()
Application.Exit()
等的调用。我已经看到了由此引起的错误--由于
OnClose()
事件处理程序中的spurios
环境。Exit()
导致事务未回滚。
protected override void OnClosing(CancelEventArgs e) {
    t.Abort();
    base.OnClosing(e);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Thread.CurrentThread.Abort();
}