2013-04-27 7 views
6

Una webapp ASP.NET 3.5 deve iniziare diverse attività che richiedono ore per essere completate. Per ovvi motivi, le pagine che iniziano queste attività non possono aspettare che finiscano, né qualcuno vorrà aspettare tanto a lungo per ottenere una risposta, quindi le attività devono essere asincrone.Attività a lunga esecuzione di ASP.NET. Si sta interrompendo l'eccezione del thread

Esiste una classe di supporto per gestire tutte queste attività a esecuzione prolungata. Il metodo principale che gli orari ed esegue questi compiti è attualmente la seguente:

public static bool ScheduleTask(TaskDescriptor task, Action action) 
{ 
    bool notAlreadyRunning = TasksAsync.TryAdd(task); 
    if (notAlreadyRunning) 
    { 
     Thread worker = null; 
     worker = new Thread(() => 
     { 
      try { action(); } 
      catch(Exception e) 
      { 
       Log.LogException(e, "Worker"); 
      } 
      TasksAsync.RemoveTask(task); 
      workers.Remove(worker); 
     }); 
     workers.Add(worker); 
     worker.Start(); 
    } 
    return notAlreadyRunning; 
} 

Su implementazioni precedenti abbiamo utilizzato l'approccio ThreadPool.QueueUserWorkItem ma il risultato è sempre stato lo stesso: dopo ca.. 20-30 minuti di interruzione di un thread è stata generata un'eccezione.

Qualcuno sa perché sta succedendo? o come può essere prevenuto?

Ulteriori informazioni:

  • IIS configurazione standard.
  • compiti potrebbero essere qualsiasi cosa, querys ad un database e/o operazioni di IO ecc

UPDATE: Le decisioni

Grazie a tutti per le vostre risposte. Ora non so quale domanda segnare come risposta. Tutti sono validi e sono possibili soluzioni a questo problema. Aspetterò oggi e segnerò come risposta la risposta con i voti più alti, in caso di parità sceglierò la prima risposta mostrata, in genere sono ordinati per la maggior rilevanza.

Per chi vuole conoscere la soluzione che scelgo, sempre a causa delle limitazioni di tempo, è stato necessario modificare la configurazione di riciclo di IIS, ma quella che considero la soluzione ideale, basata sulla mia ricerca e naturalmente sulle risposte di seguito, è necessario creare un "Servizio di lavoro" e utilizzare una soluzione di comunicazione tra l'App ASP.NET e il nuovo "Servizio di lavoro" per coordinare il lavoro di lunga durata da svolgere.

+0

I tuoi AppPool/lavoratori IIS vengono riciclati? –

+0

La configurazione di IIS è la configurazione standard per IIS 7. Quindi sì, credo. – Unlimited071

+0

È passato un po 'di tempo dall'ultima volta che ho lavorato in profondità in ASP.NET, ma se la memoria viene utilizzata, quando i processi di lavoro vengono riciclati, possono interrompere i thread. Prova a disabilitare il riciclaggio e vedi se questa è la fonte degli aborti di thread. (non sono sicuro di una soluzione alternativa se questo è il caso però, come ho detto, non ho toccato _questo_ problema particolare) –

risposta

6

È possibile avviare il processo di lunga durata nel proprio dominio dell'applicazione.

In passato, quando avevo bisogno di questa funzionalità, creo un servizio Windows per questo scopo. Se si usa WCF per connettersi ad esso, non è nemmeno necessario eseguirlo sul computer IIS; è possibile eseguirlo su qualsiasi macchina sulla rete.

+0

Penso che tu abbia ragione e questo sarebbe l'approccio da adottare, ma a causa delle restrizioni temporali non penso che potremmo farlo. – Unlimited071

+0

Non penso che tu abbia davvero una scelta. Phil Haack rende abbastanza chiaro che IIS non è progettato per farlo. Puoi provare a far girare una discussione in un nuovo appdomain: http://www.pcreview.co.uk/forums/start-thread-new-appdomain-t3614317.html –

+0

Non sapevo che potresti creare un appdomain al volo così ... credo che leggerò a riguardo. Ma se potessi salvarmi un po 'di ricerca, cosa succede all'appodominio quando il thread finisce? basicamente, come posso assicurarmi di liberare le risorse del nuovo appdomain? – Unlimited071

4

È possibile che funzioni, aumentando il timeout, utilizzando un pool di app diverso o una varietà di altri hack, ma la soluzione migliore è quella di separare l'attività a esecuzione prolungata dall'interfaccia utente e asp.net completamente, e utilizzare un servizio (non lo consiglierei) o un'attività pianificata che esegue il polling per il lavoro da eseguire; personalmente userò qualcosa come aws sqs/sns per tenere traccia del lavoro da svolgere e un'attività pianificata in Windows Server che controlla le cose da fare a qualunque frequenza abbia senso. L'unica cosa che l'ui/asp.net deve quindi fare è registrare il fatto che qualcosa deve essere fatto, in realtà non farlo.

Un altro vantaggio di questo approccio basato su messaggi è che se il processo a lungo termine diventa così lungo, o sovraccarico di lavoro, si avrà la possibilità di aggiungere più attività o server di lavoro per completare tali richieste.

Forse più di quanto tu possa implementare per il tuo problema immediato, ma qualcosa da considerare per una migliore soluzione a lungo termine.

Problemi correlati