Вопрос по wpf, c# – Отображение времени выполнения части программы в метке

2

Я пытаюсь, чтобы ярлык отображал время, которое требуется пользователю для выполнения задачи, пока он ее завершает. Таким образом, метка начинается в 00:00:00 и увеличивается с шагом в миллисекунды. Пока у меня есть это:

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

StartTimer (); вызывается по нажатию кнопки

Может ли кто-нибудь указать мне правильное направление?

Ваш Ответ

3   ответа
2

Таймер - это компонент, для которого вы можете устанавливать интервалы и вызывать метод для каждого тика. Объедините его с элементом данных секундомера, и вы получите доступ к свойству Elapsed секундомера (как вы делаете это в вашем методе ShowElapsedTime), например, каждые 50 миллисекунд.

Основная проблема в этом состоит в том, что таймер не имеет точного времени и также будет поврежден при обновлении текста метки.

Другой подход заключается в использовании потока для предотвращения блокировки пользовательского интерфейса, но затем, если вы изменили текст метки из потока, отличного от основного потока, - вы получите исключение.

Вы МОЖЕТЕ обойти это исключение, но лучшим способом было бы использовать 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 вашего класса. Или подпишитесь на событие ElapsedTimeChanged с помощью вашего метода ShowElapsedTime, за исключением того, что оно затем будет использовать свойство ElapsedTime вашего класса вместо свойства stopWatch.Elapsed.

11

чтобы ваш TextBlock связывался с элементом строки в вашей ViewModel. В вашей ViewModel вы можете использовать DispatcherTimer, чтобы установить прошедшее время. DispatcherTimer запускает свой обратный вызов в потоке пользовательского интерфейса, поэтому вам не нужно вызывать его в потоке пользовательского интерфейса.

Код:

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}"/>
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededmsdn.microsoft.com/en-us/library/…
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
1

ShowElapsedTime периодически. УвидетьТаймер обратного отсчета для примера.

Похожие вопросы