Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

3 года назад
Открыть в
День 1513. #ЗаметкиНаПолях Таймеры в .NET В .NET есть как минимум 6 разных таймеров! Каждый для своей цели и варианта использования. Рассмотрим различия между ними. Во-первых, есть специальные таймеры пользовательского интерфейса. Эти таймеры используются для выполнения кода в UI-потоке: - System.Windows.Forms.Timer - System.Windows.Threading.DispatcherTimer Эти таймеры выполняют обратный вызов в UI-потоке. Таким образом, вы можете взаимодействовать с пользовательским интерфейсом в обоих случаях. Кроме того, поскольку событие вызывается в UI-потоке, одновременно выполняется только один обратный вызов. Таким образом, вам не нужно беспокоиться о потокобезопасности. Для WebForms есть ещё один таймер: System.Web.UI.Timer. Он генерирует событие обратной передачи на сервере. Но не будем об устаревших технологиях))) Наконец, 3 таймера, которые не зависят от пользовательского интерфейса. 1. System.Threading.Timer Самый простой. Он планирует обратный вызов в ThreadPool. Если обработчику требуется больше времени для выполнения, чем интервал, обработчик будет выполнен снова, и вы получите несколько обработчиков, работающих параллельно.
var timer = new System.Threading.Timer(
  // обратный вызов может быть выполнен параллельно
  // если предыдущий ещё не завершился
  // до старта следующего
  callback: state => Console.WriteLine("tick"), 
  
  // Используется для передачи данных
  // в метод обратного вызова,
  // чтобы не использовать замыкание
  state: null, 

  // Начать немедленно
  dueTime: TimeSpan.Zero,    
       
  // Повторять каждую секунду
  period: TimeSpan.FromSeconds(1));

// Поставить таймер на паузу
timer.Change(
 dueTime: Timeout.Infinite,
 period: Timeout.Infinite);

2. System.Timers.Timer Использует System.Threading.Timer внутри и предоставляет несколько дополнительных функций, таких как AutoReset, Enabled или SynchronizingObject, которые позволяют настроить способ выполнения обратного вызова. Также событие Tick позволяет зарегистрировать несколько обработчиков. Вы также можете изменить обработчик после запуска таймера.
var timer = new System.Timers.Timer(
 TimeSpan.FromSeconds(1));

// несколько обработчиков
timer.Elapsed += (sender, e) 
  => Console.WriteLine("Handler 1");
timer.Elapsed += (sender, e)
  => Console.WriteLine("Handler 2");

// Останавливаем после 1го выполнения
timer.AutoReset = false;

// Запускаем
timer.Start();

3. System.Threading.PeriodicTimer Используется в цикле и поддерживает асинхронные обработчики. У него нет события Tick, но он предоставляет метод WaitForNextTickAsync, возвращающий ValueTask<bool>, которая завершается к концу интервала. Булев параметр указывает, был ли таймер удалён. Таким образом, можно использовать его в цикле while и обратные вызовы не могут перекрываться.
using var cts = 
 new CancellationTokenSource();
using var timer = 
 new PeriodicTimer(TimeSpan.FromSeconds(1));

while (
 await timer.WaitForNextTickAsync(cts.Token))
{
  Console.WriteLine("Tick");
  await AsyncOperation();
}

Источник: https://www.meziantou.net/too-many-timers-in-dotnet.htm