簡體   English   中英

在標簽中顯示部分程序的運行時間

[英]Display the running time of part of a program in a label

我試圖讓標簽顯示用戶完成從 00:00:00 開始的任務所花費的時間,並以顯示的毫秒增量從那里開始。 到目前為止,我有這個:

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

startTimer(); 單擊按鈕時調用

有人可以指出我正確的方向嗎?

我建議采用 MVVM 方法。 將 TextBlock 綁定到 ViewModel 上的字符串成員。 在您的 ViewModel 中,您可以使用 DispatcherTimer 來設置經過的時間。 DispatcherTimer 在 UI 線程上觸發其回調,因此您無需調用 UI 線程。

代碼:

public class ViewModel : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;
     public string 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:

<TextBlock Text="{Binding TimeElapsed}"/>

簡單的方法是使用計時器(不是秒表)。 計時器是一個組件,您可以在每個刻度上設置間隔並調用一個方法。 例如,結合秒表的數據成員,您可以每 50 毫秒訪問一次秒表的 Elapsed 屬性(就像您在 ShowElapsedTime 方法中所做的那樣)。

這樣做的主要問題是計時器不是完全定時的,並且在標簽文本更新時也會出現顛簸。

一種不同的方法是使用線程來防止 UI 鎖定,但是如果您從主線程以外的線程更改了標簽文本,則會出現異常。

您可以繞過該異常,但更好的方法是使用 BackgroundWorker。

BGWorker 將在不同的線程中執行任務,您可以讓它報告進度,在主線程中調用。

如果您真的想完美解決它,請使用一個實現 INotifyPropertyChanged 的​​類,該類具有一個屬性 ElapsedTime 和一個私有的 StopWatch 數據成員。 該類將按以下方式使用 BackgroundWorker。

在演員:

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

當您想啟動工作程序(又名啟動計時器)時:

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

當你想停止工作人員(又名停止計時器)時:

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

類本身將有一個 Start 和 Stop 方法,它們將與工作人員(數據成員)進行交互。

最后,您可以將標簽文本綁定到類的 ElapsedTime 屬性。 或者使用您的 ShowElapsedTime 方法訂閱 ElapsedTimeChanged 事件,但它將使用您的類的 ElapsedTime 屬性而不是 stopWatch.Elapsed 屬性。

您需要一個定期調用ShowElapsedTime的計時器。 有關示例,請參閱WPF 計時器倒計時

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM