ObjectDisposedException - запуск секундомера в потоке графического интерфейса - PullRequest
1 голос
/ 15 января 2010

У меня есть секундомер, работающий в другом потоке, который обновляет поток 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;
        }

Ответы [ 2 ]

2 голосов
/ 15 января 2010

Тот же код, теперь использующий 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 (), невозможно перенаправлять вызовы в поток пользовательского интерфейса более 1000 раз в секунду.

2 голосов
/ 15 января 2010

Как это выглядит, секундомер удаляется, когда вы закрываете свое приложение, но поток все еще работает и пытается его использовать. Можете ли вы остановить свою ветку перед закрытием приложения (в событии FormClosing)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...