таймеры
.NET предоставляет три таймера для использования в многопоточной среде:
- System.Threading.Timer, который выполняет метод одного обратного вызова в потоке ThreadPool с регулярными интервалами.
- System.Timers.Timer, который по умолчанию порождает событие в потоке ThreadPool с регулярными интервалами.
- System.Threading.PeriodicTimer, который позволяет вызывающим выполнять работу после ожидания отдельных галок таймера.
Примечание.
В некоторых реализациях .NET может содержать дополнительные таймеры:
- System.Windows.Forms.Timer — компонент Windows Forms, который вызывает событие через определенные интервалы времени. У этого компонента нет интерфейса пользователя. Он предназначен для однопоточной среды.
- System.Web.UI.Timer — компонент ASP.NET, который выполняет асинхронную или синхронную обратную передачу веб-страницы с регулярными интервалами.
- System.Windows.Threading.DispatcherTimer — таймер, интегрированный в очередь Dispatcher, которая обрабатывается с заданными интервалом и приоритетом.
Класс System.Threading.Timer
Класс System.Threading.Timer позволяет непрерывно вызывать делегат через определенные интервалы времени. Этот класс также можно использовать, чтобы запланировать один вызов делегата через указанный интервал времени. Делегат выполняется в потоке ThreadPool.
При создании объекта System.Threading.Timer вы указываете делегат TimerCallback, который определяет метод обратного вызова, необязательный объект состояния, который передается обратному вызову, временную задержку до первого вызова обратного вызова и интервал времени между вызовами обратного вызова. Чтобы отменить ожидающий таймер, вызовите метод Timer.Dispose.
В следующем примере создается таймер, который вызывает предоставленный делегат в первый раз через одну секунду (1000 миллисекунд), а затем каждые две секунды. Объект состояния в примере используется для подсчета вызовов делегата. Таймер останавливается после 10 вызовов.
using namespace System;
using namespace System::Threading;
ref class TimerState
{
public:
int counter;
};
ref class Example
{
private:
static Timer^ timer;
public:
static void TimerTask(Object^ state)
{
Console::WriteLine("{0:HH:mm:ss.fff}: starting a new callback.", DateTime::Now);
TimerState^ timerState = dynamic_cast<TimerState^>(state);
Interlocked::Increment(timerState->counter);
}
static void Main()
{
TimerCallback^ tcb = gcnew TimerCallback(&TimerTask);
TimerState^ state = gcnew TimerState();
state->counter = 0;
timer = gcnew Timer(tcb, state, 1000, 2000);
while (state->counter <= 10)
{
Thread::Sleep(1000);
}
timer->~Timer();
Console::WriteLine("{0:HH:mm:ss.fff}: done.", DateTime::Now);
}
};
int main()
{
Example::Main();
}
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static Timer timer;
static void Main(string[] args)
{
var timerState = new TimerState { Counter = 0 };
timer = new Timer(
callback: new TimerCallback(TimerTask),
state: timerState,
dueTime: 1000,
period: 2000);
while (timerState.Counter <= 10)
{
Task.Delay(1000).Wait();
}
timer.Dispose();
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.");
}
private static void TimerTask(object timerState)
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.");
var state = timerState as TimerState;
Interlocked.Increment(ref state.Counter);
}
class TimerState
{
public int Counter;
}
}
Imports System.Threading
Module Program
Private Timer As Timer
Sub Main(args As String())
Dim StateObj As New TimerState
StateObj.Counter = 0
Timer = New Timer(New TimerCallback(AddressOf TimerTask), StateObj, 1000, 2000)
While StateObj.Counter <= 10
Task.Delay(1000).Wait()
End While
Timer.Dispose()
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.")
End Sub
Private Sub TimerTask(ByVal StateObj As Object)
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.")
Dim State As TimerState = CType(StateObj, TimerState)
Interlocked.Increment(State.Counter)
End Sub
Private Class TimerState
Public Counter As Integer
End Class
End Module
Дополнительные сведения и примеры см. на сайте System.Threading.Timer.
Класс System.Timers.Timer
Еще один таймер, который может использоваться в многопоточной среде, — System.Timers.Timer. По умолчанию он порождает событие в потоке ThreadPool.
При создании объекта System.Timers.Timer вы можете указать интервал времени, в котором порождается событие Elapsed. Используйте свойство Enabled, чтобы указать, должен ли таймер порождать событие Elapsed. Если вам нужно, чтобы событие Elapsed вызывалось только один раз по истечении заданного интервала, установите для AutoReset значение false
. Свойство AutoReset по умолчанию имеет значение true
, то есть событие Elapsed вызывается регулярно с интервалом, определенным в свойстве Interval.
Дополнительные сведения и примеры см. на сайте System.Timers.Timer.
Класс System.Threading.PeriodicTimer
Класс System.Threading.PeriodicTimer позволяет ожидать отдельные галочки заданного интервала, выполняя работу после вызова PeriodicTimer.WaitForNextTickAsync.
При создании System.Threading.PeriodicTimer объекта указывается TimeSpan , что определяет продолжительность времени между каждым тиком таймера. Вместо передачи обратного вызова или настройки обработчика событий, как и в предыдущих классах таймера, вы выполняете работу непосредственно в область, ожидая WaitForNextTickAsync продвижения таймера по указанному интервалу.
Метод WaitForNextTickAsync возвращает значение ; true
после успешного запуска таймера и false
при отмене таймера вызовомPeriodicTimer.DisposeValueTask<bool>
. WaitForNextTickAsync При необходимости принимает значение CancellationToken, которое приводит к TaskCanceledException запросу отмены.
Дополнительные сведения см. в разделе System.Threading.PeriodicTimer.