Di solito curiosità e idee mi nascono durante le pause di riflessione, quindi: quando vado a nanna o in bagno :-D
Questa volta però lo spunto mi è venuto mentre seguivo una sessione di Paolo su Indigo. Ah ecco, perché dormivo...:-D Ovviamente scherzo!
Indigo presta, o meglio presterà attenzione al relying dei servizi con lo scopo di non perdere lo stato di operazioni interrotte a causa di ricicli di processi o di AppDomain. Mi son quindi chiesto come in ASP.NET questo possa essere fatto e più in generale come avviene il riciclo.
La classe da guardare è HttpRuntime. E' presente un metodo pubblico e statico UnloadAppDomain i cui effetti si ottengono modificando il web.config e cioè, il riciclo dell'AppDomain. In pratica quando il web.config o il global.asax o la directory bin o il file di policy cambiano o quando si verificano errori in fase di init viene richiamato il metodo ShutdownAppDomain. Questo imposta una variabile privata _shutDownMessage accumulativa dei messaggi che viene solo valorizzata, ma usata da nessuno (anche perché nel reciclarsi l'appDomain viene persa). Successivamente se si trova alla prima richiesta attende qualche secondo, dipende dall'attributo system.web/httpRuntime/@delayNotificationTimeout (non documentato) o 5 secondi se non presente.
In seguito richiama l'API AppDomainRestart della dll aspnet_isapi.dll e successivamente un callback mantenuto tramite la variabile _appDomainUnloadallback (errore d'ortografia non mio ;-)) fatto eseguire da un thread pool. Questo callback non fa altro che usare il metodo AppDomain.Unload per scaricare l'appDomain corrente. In pratica scarica normalmente l'appDomain ma prima avvisa il worker process di asp.net che dovrà avviarlo. Se non lo fa vi troverete col messaggio classico "Application unavailable".
Per fare un po' di test ho fatto questa classe. Volendo si può usare anche in produzione, ma con la dovuta cautela. La classe lavora tramite reflection e permette di agganciare un evento quando viene richiesto il riciclo dell'AppDomain, di sapere la motivazione (tramite _shutDownMessage) e di eseguire eventualmente qualche operazione.
Nella pratica, sostituisce il callback con uno mio il quale, legge il motivo, scatena l'evento e scatena il callback originale. I messaggi possibili possono essere:
- Overwhelming Change Notification in "directory"
- User code called UnloadAppDomain
- Physical application path changed from to
- CONFIG change
- Change in GLOBAL.ASAX
- Change in code-access security policy file
- Initialization Error
Magari mandare un e-mail in qualcuno di questi casi può essere utile. E' presente anche una proprietà EnableRestart che in pratica imposta a null l'_appDomainId. In fase di shutdown questo field fa saltare il restart dell'appDomain. Provate a settarla a false e vedrete che una volta scaricato l'appDomain le richieste non vengono più soddisfatte. Vi starete chiedendo, a cosa serve? A niente! :-D
Un'ultima cosa. Cosa succede ai thread e alle operazioni che si stanno eseguendo in quel momento? Un thread apposito per l'unload effettua un Abort del thread quindi potete intercettare l'eccezione ThreadAbortException.
Raccomando comunque di non prolungare l'attesa al processo di chiusura dell'appDomain sia all'interno dell'eccezione sia nell'evento del riciclo.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- LINQ, lazy loading e architettura, l'11 marzo 2011 alle 18:42
- MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010, il 7 gennaio 2010 alle 13:58
- .NET Framework 4.0 beta 1: Windows Communication Foundation, il 18 maggio 2009 alle 16:00
- Parallelizzare in Silverlight 2.0, il 21 aprile 2009 alle 00:25
- Silverlight: performance dell'isolated storage, il 16 aprile 2009 alle 17:38
- MetadataDiffViewer: differenze tra i framework, il 15 aprile 2009 alle 18:56