【问题标题】:ObjectDisposedException - running stopwatch in GUI threadObjectDisposedException - 在 GUI 线程中运行秒表
【发布时间】:2010-01-14 22:06:45
【问题描述】:

我有一个秒表在不同的线程中运行,它会更新标签中的 GUI 线程以随着时间的推移显示。当我的程序关闭时,当我在表单 GUI 中调用 this.Invoke(mydelegate); 以使用秒表中的时间更新标签时,它会抛出 ObjectDisposedException

如何摆脱这个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;
        }

【问题讨论】:

    标签: c# multithreading timer stopwatch objectdisposedexception


    【解决方案1】:

    看起来是当您关闭应用程序时正在释放秒表,但线程仍在运行并尝试使用它。在关闭应用程序之前(在 FormClosing 事件中)可以先停止线程吗?

    【讨论】:

    • 我也强烈建议为此使用 BackgroundWorker。我很高兴这解决了问题
    【解决方案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 次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 2013-08-21
      • 2011-05-24
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      相关资源
      最近更新 更多