Таймер обратного отсчета останавливается в случайных точках - PullRequest
0 голосов
/ 15 марта 2012

У меня есть приложение, которое требует нескольких таймеров обратного отсчета для запуска (некоторые одновременно). Они также обновляют элементы интерфейса с оставшимся временем на обратном отсчете. Я попытался использовать DispatcherTimer для его простого способа взаимодействия с элементами пользовательского интерфейса. Однако после 300-секундного обратного отсчета он становится не синхронизированным с реальным временем (из-за интенсивного обновления пользовательского интерфейса) до такой степени, что у меня остается 30 секунд на таймере, когда оно должно быть 0.

Затем я попытался переключиться на System.Threading.Timer (код ниже). Теперь таймер активирован и синхронизирован с реальным временем. Тем не менее, таймер перестает тикать после случайного числа тиков (от 3 до 60 секунд). Я подозреваю, что это либо сборщик мусора, либо Invoke (используется для обновления пользовательского интерфейса), но на самом деле у него нет знаний, чтобы продолжать идти по этому пути. Кто-нибудь может дать мне какое-либо представление о том, почему таймер случайно останавливается?

private int counter = 500;    
private void btnTopBlue_Click(object sender, RoutedEventArgs e)
{
    btnTopBlue.Content = counter.ToString();
    Timer dt = new Timer(topBlue_Tick, null, 1000, 1000);
}
private void topBlue_Tick(object sender)
{
     if (counter > 0)
     {
         counter--;
         Dispatcher.BeginInvoke(() => btnTopBlue.Content = counter.ToString());    
     }
     else
         ((Timer)sender).Dispose();
 }

Ответы [ 2 ]

2 голосов
/ 15 марта 2012

Не в счет. Сравните текущее время с временем начала таймера и выполните математические расчеты. Таким образом, даже если вы пропустите полсекунды здесь и полсекунды, вы все равно будете вовремя.

Рассмотрим этот код:

    private static DateTime EndTime { get; set; }

    private void Button_Click(object sender, RoutedEventArgs e)
    {

        DispatcherTimer dt = new DispatcherTimer();
        dt.Interval = TimeSpan.FromSeconds(.1);


        dt.Tick += (s, evt) =>
                       {
                           var remaining = EndTime - DateTime.Now;

                           timeRemaining.Text = string.Format("{0:0.0}", remaining.TotalSeconds);

                           if(remaining.TotalSeconds <= 0)
                           {
                               dt.Stop();
                           }
                       };

        EndTime = DateTime.Now + TimeSpan.FromSeconds(30);
        dt.Start();

    }
0 голосов
/ 15 марта 2012

Это случилось со мной для службы, которую я писал. Таймер в конце концов остановится, и при отладке процесса обнаружится, что потоки были собраны в мусор. Мне было предложено, что установка свойства .IsBackground = true исправит это. В итоге я сделал что-то другое, поэтому у меня не было возможности попробовать это. Это может помочь вам, хотя.

...