我有一个在不同线程中运行的秒表,它会更新标签中的GUI线程,以便随着时间的推移显示。当我的程序关闭时,当我在表单GUI中调用ObjectDisposedException
时,它会使用秒表中的时间更新标签时抛出this.Invoke(mydelegate);
。
如何摆脱这个ObjectDisposedException
?
我试图在FormClosing事件中停止秒表,但它没有处理它。
以下是代码:
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
stopwatch = sw;
sw.Start();
//System.Threading.Thread.Sleep(100);
System.Threading.Thread t = new System.Threading.Thread(delegate()
{
while (true)
{
TimeSpan ts = sw.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
timeElapse = elapsedTime;
UpdateLabel();
}
});
stopwatchThread = t;
t.Start();
public void UpdateLabel()
{
db = new doupdate(DoUpdateLabel);
this.Invoke(db);
}
public void DoUpdateLabel()
{
toolStripStatusLabel1.Text = timeElapse;
}
答案 0 :(得分:2)
当您关闭应用程序时,Stopwatch正在处理,但线程仍在运行并尝试使用它。您可以在关闭应用程序之前先停止您的线程吗(在FormClosing事件中)?
答案 1 :(得分:2)
相同的代码,现在使用BackgroundWorker和有序关闭,确保在后台线程首先停止运行之前表单不会关闭:
using System;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
backgroundWorker1.WorkerReportsProgress = backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.RunWorkerAsync();
}
bool mCancel;
void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
if (e.Error != null) MessageBox.Show(e.Error.ToString());
if (mCancel) this.Close();
}
protected override void OnFormClosing(FormClosingEventArgs e) {
if (backgroundWorker1.IsBusy) mCancel = e.Cancel = true;
backgroundWorker1.CancelAsync();
}
void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) {
label1.Text = e.UserState as string;
}
void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
Stopwatch sw = Stopwatch.StartNew();
while (!backgroundWorker1.CancellationPending) {
TimeSpan ts = sw.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
backgroundWorker1.ReportProgress(0, elapsedTime);
Thread.Sleep(15);
}
}
}
}
请注意,Sleep()调用是必需的,不可能每秒调用UI线程超过1000次。