[英]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.