Come tutti sappiamo, ASP non permette di eseguire operazioni asincrone, ovvero tutte le operazioni devono concludersi nel ciclo di vita (e di invio al browser) della pagina in questione.
Fortunatamente ASP.NET è migliore di ASP anche su questo punto e ci consente di utilizzare dei meccanismi per gestire in maniera asincrona determinati eventi.
In questo articolo vedremo le basi per realizzare ciò che è stato sempre impossibile con ASP, se non con l'ausilio di Windows Services o di oggetti COM, che solo poche persone possono permettersi di installare su un server web.
ASP.NET ci viene incontro grazie al nuovo concetto di programmazione web introdotto da Microsoft, il quale ci consente di trattare un'applicazione web come se stessimo programmandone una desktop.
Anatomia di una richiesta
Quando richiamiamo una pagina ASP.NET per la prima volta, il framework crea un istanza della classe HttpApplication del namespace System.Web. Questa classe è la madre dell'intera applicazione web e resterà in vita finché l'applicazione non terminerà (riavvio del framework, di IIS o della macchina) ed è, ovviamente, il motore delle nostre pagine.
Gestisce vari eventi che la riguardano, come l'inizio di una richiesta di una pagina, l'avvio e il termine dell'applicazione, intercettando gli eventi dal file global.asax , contettualmente simile al vecchio global.asa: di conseguenza possiamo creare variabili o oggetti che resteranno in vita per l'intera applicazione .
Per raggiungere il nostro scopo useremo la classe Timer del namespace System.Timers, la quale richiama un evento dopo aver trascorso un intervallo di tempo da noi stabilito.
Gli eventi nel global.asax
Per capire meglio come funziona in fondo ASP.NET, erediteremo la classe HttpApplication personalizzandola in modo da far eseguire le nostre operazioni, grosso modo come nel codebehind delle pagine ASP.NET.
Per prima cosa creiamo il file global.asax nella nostra applicazione web, scrivendo solo questa riga:
<%@ Application language="c#" inherits="MyGlobal" Classname="MainApp" %>
Il primo attributo lo si conosce: Inherits indica, come nelle pagine ASP.NET, che vogliamo utilizzare una nostra classe da cui l'attuale erediterà, perciò ne indichiamo il nome.
L'attribuito Classname indica il nome dell'istanza della classe HttpApplication che .NET creerà: questo ci permetterà di accedere a variabili o oggetti della classe stessa in seguito.
A questo punto dobbiamo creare un file global.cs che conterrà la nostra classe:
using System; public class MyGlobal:HttpApplication { public MyGlobal():base() { //operazioni di inizio } }
Passiamo alla compilazione con VS.NET, oppure direttamente da riga di comando, assicurandoci di essere nella stessa directory dove è posizionato il file global.cs:
csc /out:bin/global.dll /target:library /r:system.dll /r:system.web.dll global.cs
Se eseguiamo una pagina normale ASP.NET dell'applicazione web, la pagina stessa verrà restituita normalmente. Chi usa VS.net troverà questo lavoro già fatto perché di norma viene creata una classe che eredita HttpApplication.
L'oggetto timer
A questo punto possiamo creare il nostro oggetto timer e far sì che rimanga in vita (e quindi pronto per essere utilizzato) per l'intera vita dell'applicazione.
Definiamo due variabili statiche e pubbliche che indicano quando l'operazione deve essere eseguita e ogni quante ore deve ripetersi l'operazione.
Il vantaggio di utilizzare variabili statiche consiste nella loro validità all'interno di tutte le istanze della stessa classe.
public static DateTime When; public static byte Every;
Definiamo quindi la nostra variabile Timer:
private Timer OpTimer;
Nella nostra sub costruttrice definiamo l'orario della prima esecuzione e avviamo il nostro timer:
When=DateTime.Parse("16:08"); Every=1; StartTimer();
Definiamo l'ora di avvio nella variabile When: in questo modo all'avvio dell'applicazione l'ora verrà parserizzata con la data odierna. Every indica il numero di ore di intervallo.
Aggiungiamo una sub StartTimer, che si occuperà di calcolare l'ora esatta di esecuzione:
private void StartTimer() { if (When<DateTime.Now) { while (When<=DateTime.Now){ When=When.AddHours(Every); } } opTimer=new Timer(GetInterval()); OpTimer.AutoReset=false; OpTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent); OpTimer.Enabled=true; }
Innanzitutto controlliamo che l'ora di inizio non sia inferiore all'ora corrente: in questo caso aumenteremo l'ora della prima esecuzione aggiungendo l'intervallo stabilito finché non sia maggiore dell'ora odierna.
Ad esempio:
When è uguale a 10/10/2002 10:00
DateTime.Now è uguale a 10/10/2002 09:00
Se Every è 24 il nostro ciclo while terminerà con un When di valore: 11/10/02 10:00.
A questo punto dobbiamo istanziare un nuovo timer indicando l'intervallo (in millisecondi) di esecuzione, che calcoleremo con una funzione GetInterval, che analizzeremo nel dettaglio tra qualche riga.
Attenzione: Questo articolo contiene un allegato.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.