Timer
.NET fornisce tre timer da usare in un ambiente con multithreading:
- System.Threading.Timer, che esegue un metodo di callback singolo su un thread ThreadPool a intervalli regolari.
- System.Timers.Timer, che per impostazione predefinita genera un evento in un thread ThreadPool a intervalli regolari.
- System.Threading.PeriodicTimer, che consente al chiamante di eseguire il lavoro dopo l'attesa di singoli tick del timer.
Nota
Alcune implementazioni .NET possono includere altri timer:
- System.Windows.Forms.Timer: un componente di Windows Form che genera un evento a intervalli regolari. Il componente non dispone di interfacce utente ed è progettato per l'uso in un ambiente a thread singolo.
- System.Web.UI.Timer: un componente ASP.NET che esegue postback asincroni o sincroni di pagina Web in base a intervalli regolari.
- System.Windows.Threading.DispatcherTimer: un timer integrato nella coda del Dispatcher che viene elaborata in un intervallo di tempo specifico e con una priorità specifica.
Classe System.Threading.Timer
La classe System.Threading.Timer consente di chiamare in modo continuativo un delegato a determinati intervalli di tempo. È inoltre possibile usare questa classe per pianificare una singola chiamata a un delegato in un intervallo di tempo specifico. Il delegato viene eseguito su un thread ThreadPool.
Quando si crea un oggetto System.Threading.Timer, si specifica un delegato TimerCallback che definisce il metodo di callback, un oggetto di stato facoltativo passato al callback, il tempo di attesa prima della prima chiamata di callback e l'intervallo di tempo tra le chiamate di callback. Per annullare un timer in sospeso, chiamare il metodo Timer.Dispose.
L'esempio seguente illustra come creare un timer che chiama il delegato fornito per la prima volta dopo un secondo (1000 millisecondi) e quindi ogni due secondi. L'oggetto di stato nell'esempio viene usato per contare quante volte viene chiamato il delegato. Il timer viene arrestato dopo aver chiamato il delegato almeno 10 volte.
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
Per altre informazioni ed esempi, vedere System.Threading.Timer.
Classe System.Timers.Timer
Un altro timer utilizzabile in un ambiente con multithreading è System.Timers.Timer, che per impostazione predefinita genera un evento in un thread ThreadPool.
Quando si crea un oggetto System.Timers.Timer, è possibile specificare l'intervallo di tempo in cui si desidera generare un evento Elapsed. Usare la proprietà Enabled per indicare se un timer deve generare un evento Elapsed. Se un evento Elapsed deve essere generato una sola volta dopo l'intervallo specificato, impostare AutoReset su false
. Il valore predefinito della proprietà AutoReset è true
, vale a dire che un evento Elapsed viene generato periodicamente in base all'intervallo definito dalla proprietà Interval.
Per altre informazioni ed esempi, vedere System.Timers.Timer.
Classe System.Threading.PeriodicTimer
La classe System.Threading.PeriodicTimer consente di attendere i singoli tick di un intervallo specificato, eseguendo il lavoro dopo aver chiamato PeriodicTimer.WaitForNextTickAsync.
Quando si crea un oggetto System.Threading.PeriodicTimer, si specifica un TimeSpan che determina l'intervallo di tempo tra ogni tick del timer. Anziché passare un callback o impostare un gestore eventi come nelle classi timer precedenti, è possibile eseguire operazioni direttamente nell'ambito, in attesa che WaitForNextTickAsync faccia avanzare il timer in base all'intervallo specificato.
Il metodo WaitForNextTickAsync restituisce un ValueTask<bool>
; true
al completamento dell'attivazione del timer e false
quando il timer è stato annullato chiamando PeriodicTimer.Dispose. WaitForNextTickAsync facoltativamente accetta un CancellationToken, che comporta un TaskCanceledException quando è stato richiesto un annullamento.
Per ulteriori informazioni, vedere System.Threading.PeriodicTimer.