Spesso nelle nostre applicazioni, ci troviamo a dover eseguire operazioni a intervalli regolari, per esempio per verificare se un utente è ancora connesso, pulire il contenuto di una tabella o effettuare il polling su una risorsa.
Una possibile soluzione, se siamo su Azure, è quella di utilizzare una Function con time trigger, con la complessità però di avere un'ulteriore "moving part" nella nostra architettura.
Un'alternativa più semplice è sfruttare gli hosted service di ASP.NET Core, che vengono eseguiti in automatico dal runtime come processi di background.
Ciò che dobbiamo fare è realizzare una classe che implementi l'interfaccia IHostedService:
internal class MyTimedService : IHostedService, IDisposable { private Timer _timer; private ILogger<MyTimedService> _logger; public MyTimedService(ILogger<MyTimedService> logger) { _logger = logger ?? throw new ArgumentNullException("logger"); } public Task StartAsync(CancellationToken cancellationToken) { _timer = new Timer( async state => { try { cancellationToken.ThrowIfCancellationRequested(); // ... nostra logica qui ... } catch (Exception ex) { _logger.LogError(ex, "Failed to execute"); } }, state:null, dueTime:TimeSpan.Zero, // questo è il delay per la prima esecuzione period:TimeSpan.FromMinutes(1)); // ogni minuto return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer.Change(Timeout.Infinite, Timeout.Infinite); return Task.CompletedTask; } public void Dispose() { _timer.Dispose(); } }
Questa interfaccia si compone di due metodi, StartAsync e StopAsync, che il runtime invocherà per avviare e arrestare le operazioni.
In StartAsync creiamo un oggetto timer con un delegate che conterrà la nostra logica, da ripetere - nell'esempio - ogni minuto.
Il codice è piuttosto semplice, tuttavia ci sono un paio di accorgimenti a cui dobbiamo prestare attenzione. Il primo è relativo all'esecuzione, che deve avvenire all'interno di un blocco Try...Catch. In caso contrario, un'eccezione nel task porterebbe al crash dell'intera applicazione.
Il secondo è l'uso del cancellation token, che viene impostanto nel caso in cui è stato richiesto lo shutdown dell'applicazione durante l'avvio del nostro servizio. Nel nostro esempio verifichiamo lo stato all'inizio di ogni iterazione, ma, in casi più complessi, è buona norma passarlo anche alle componenti che lo supportano, in modo da interrompere task potenzialmente lunghi, come una richiesta HTTP per esempio.
Nella fase di StopAsync, invece, ci limitiamo a impostare il timer a Infinite per disabilitarlo.
Ultima nota riguarda l'interfaccia IDisposable. Questo metodo viene tipicamente richiamato in fase di shutdown, ma è sempre buona norma invocare il Dispose delle risorse utilizzate (in questo caso il nostro oggetto Timer).
Per attivare questo componente, è sufficiente registrarlo nei servizi durante la fase di startup:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddHostedService<MyTimedService>(); }
In un prossimo script, vedremo come iniettare servizi nel nostro task, così da renderlo ancora più versatile.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
-
Load test di ASP.NET Core con k6
-
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
-
Ottimizzazione dei block template in Angular 17
-
Modificare i metadati nell'head dell'HTML di una Blazor Web App
-
Semplificare il deployment di siti statici con Azure Static Web App
-
Accesso sicuro ai secrets attraverso i file in Azure Container Apps
-
Gestire errori funzionali tramite exception in ASP.NET Core Web API
-
Short-circuiting della Pipeline in ASP.NET Core
-
Utilizzare la libreria Benchmark.NET per misurare le performance
-
Aggiungere interattività lato server in Blazor 8
-
Effettuare chiamate con versioning da Blazor ad ASP.NET Core
-
Evitare il flickering dei componenti nel prerender di Blazor 8
I più letti di oggi
- Vuoi incontrare Bill Gates? Viaggia con ASPItalia.com!
- Customizzare il pager del DataGrid
- Stabilire un collegamento VPN tra una Web App e una Virtual Network
- Documentare ASP.NET Web API con Swagger
- Usare i servizi REST di BING per ottenere informazioni sulla posizione dell'utente
- Visual Studio 2005 CTP May