2010-01-14 18 views
1

J'ai un chronomètre exécuté dans un thread différent, qui met à jour le thread GUI dans une étiquette pour montrer que le temps passe. Lorsque mon programme se ferme, il lance un ObjectDisposedException lorsque j'appelle this.Invoke(mydelegate); dans l'interface graphique de formulaire pour mettre à jour l'étiquette avec l'heure du chronomètre.ObjectDisposedException - chronomètre en cours d'exécution dans le thread GUI

Comment puis-je me débarrasser de ce ObjectDisposedException?

J'ai essayé d'arrêter le chronomètre dans l'événement FormClosing, mais il ne le gère pas.

Voici le code:

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

pouvez-vous poster le code? – hackerhasid

Répondre

2

Ce qu'il ressemble le chronomètre est disposé lorsque vous fermez votre application, mais le fil est toujours en cours d'exécution et d'essayer de l'utiliser. Pouvez-vous arrêter votre thread avant de fermer l'application (dans l'événement FormClosing)?

+2

Je recommande fortement d'utiliser un BackgroundWorker pour cela. Je suis content que cela a résolu le problème – SwDevMan81

2

Même code, en utilisant maintenant un BackgroundWorker et un arrêt ordonné qui assure la forme ne se ferme pas tant que le thread d'arrière-plan a cessé de fonctionner d'abord:

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); 
      } 
     } 
    } 
} 

Notez que l'appel Sleep() est nécessaire, il n'est pas possible de marshaler les appels au thread UI plus d'environ 1000 fois par seconde.

+0

+1 Very nice !!! Merci pour ça!!! :) –