C# 关闭表单时出现异常(线程调用)
我刚刚开始学习c#中的线程和方法调用,但我遇到了一个无法解决的问题 我制作了一个基本的C#form程序,通过启动一个线程并调用委托来不断更新和显示一个数字 在Form1_load上启动新线程: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始终显
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();
}