Afficher le temps d’exécution d’une partie d’un programme dans une étiquette

J’essaie de faire en sorte qu’une étiquette affiche le temps qu’il faut à l’utilisateur pour terminer une tâche pendant qu’il la termine. Ainsi, l’étiquette commence à 00:00:00 et augmente par incréments de millisecondes à partir de là. Jusqu’ici j’ai ceci:

private void startTimer() { stopWatch.Start(); Dispatcher.BeginInvoke(DispatcherPriority.Render, new ThreadStart(ShowElapsedTime)); } void ShowElapsedTime() { TimeSpan ts = stopWatch.Elapsed; lblTime.Text = Ssortingng.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10); } 

startTimer (); est appelé sur un clic de bouton

Quelqu’un peut me diriger dans la bonne direction?

Je recommanderais d’adopter une approche MVVM. Demandez à votre TextBlock de se lier à un membre de chaîne sur votre ViewModel. Dans votre ViewModel, vous pouvez utiliser un DispatcherTimer pour définir le temps écoulé. DispatcherTimer déclenche son rappel sur le thread d’interface utilisateur, vous n’avez donc pas besoin d’appeler sur le thread d’interface utilisateur.

Code:

 public class ViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public ssortingng TimeElapsed {get;set;} private DispatcherTimer timer; private Stopwatch stopWatch; public void StartTimer() { timer = new DispatcherTimer(); timer.Tick += dispatcherTimerTick_; timer.Interval = new TimeSpan(0,0,0,0,1); stopWatch = new Stopwatch(); stopWatch.Start(); timer.Start(); } private void dispatcherTimerTick_(object sender, EventArgs e) { TimeElapsed = stopWatch.Elapsed.TotalMilliseconds; // Format as you wish PropertyChanged(this, new PropertyChangedEventArgs("TimeElapsed")); } } 

XAML:

  

Le moyen le plus simple serait d’utiliser un minuteur (pas un chronomètre). Le minuteur est un composant pour lequel vous pouvez définir des intervalles et invoquer une méthode à chaque tick. Combinez avec un membre de données d’un chronomètre et vous pourrez accéder à la propriété Elapsed du chronomètre (comme vous le faites dans votre méthode ShowElapsedTime) toutes les 50 millisecondes, par exemple.

Le principal problème avec cela serait que le chronomètre n’est pas parfaitement chronométré et sera également cahoteux lors de la mise à jour du texte de l’étiquette.

Une approche différente consisterait à utiliser un thread pour empêcher l’interface utilisateur de se verrouiller, mais si vous modifiez le texte de l’étiquette à partir d’un thread autre que votre thread principal, vous obtenez une exception.

Vous POUVEZ contourner cette exception, mais le meilleur moyen serait d’utiliser BackgroundWorker.

BGWorker effectuera la tâche dans un thread différent et vous pourrez le laisser signaler la progression, afin qu’il soit appelé dans le thread principal.

Si vous voulez vraiment être parfait à ce sujet, utilisez une classe implémentant INotifyPropertyChanged ayant la propriété ElapsedTime et un membre de données StopWatch privé. La classe utilisera BackgroundWorker de la manière suivante.

Au ctor:

 this._stopwatch = new Stopwatch(); this._worker = new BackgroundWorker {WorkerReportsProgress = true, WorkerSupportsCancellation = true}; _worker.DoWork += (s, e) => { while (!_worker.CancellationPending) { _worker.ReportProgress(0, watch.Elapsed); Thread.Sleep(1); } }; _worker.ProgressChanged += (s, e) => { this.ElapsedTime = (TimeSpan)e.UserState; }; 

Lorsque vous voulez démarrer le travailleur (ou démarrer le minuteur):

 stopwatch.Start(); _worker.RunWorkerAsync(); 

Et quand vous voulez arrêter le travailleur (aka arrêter le chronomètre):

 stopwatch.Reset(); _worker.CancelAsync(); 

La classe elle-même aura des méthodes Start et Stop qui interagiront avec le worker (membre de données).

Enfin, vous pouvez lier le texte de l’étiquette à la propriété ElapsedTime de votre classe. Vous pouvez également vous abonner à un événement ElapsedTimeChanged avec votre méthode ShowElapsedTime, sauf que la propriété ElapsedTime de votre classe sera utilisée à la place de la propriété stopWatch.Elapsed.

Vous avez besoin d’une timer qui appellera ShowElapsedTime périodiquement. Voir le compte à rebours du temporisateur WPF pour un exemple.