2010-05-19 3 views
7

Quindi mi è stato detto che quello che sto facendo qui è sbagliato, ma non sono sicuro del perché.I thread di background sono una cattiva idea? Perché?

Ho una pagina Web che importa un file CSV con numeri di documento per eseguire un'operazione costosa. Ho inserito l'operazione costosa in un thread in background per impedirne il blocco dell'applicazione. Ecco cosa ho in poche parole.

protected void ButtonUpload_Click(object sender, EventArgs e) 
{ 
    if (FileUploadCSV.HasFile) 
    { 
     string fileText; 
     using (var sr = new StreamReader(FileUploadCSV.FileContent)) 
     { 
      fileText = sr.ReadToEnd(); 
     } 

     var documentNumbers = fileText.Split(new[] {',', '\n', '\r'}, StringSplitOptions.RemoveEmptyEntries); 

     ThreadStart threadStart =() => AnotherClass.ExpensiveOperation(documentNumbers); 
     var thread = new Thread(threadStart) {IsBackground = true}; 
     thread.Start(); 
    } 
} 

(ovviamente con qualche errore di controllo & messaggi per gli utenti gettati in)

Quindi la mia domanda è triplice:

  • a) Si tratta di una cattiva idea?
  • b) Perché questa è una cattiva idea?
  • c) Cosa faresti invece?

risposta

8

Un possibile problema è che il thread in background è in esecuzione nel pool di applicazioni dei siti Web. IIS può decidere di riciclare il pool di applicazioni causando la distruzione dell'operazione costosa prima che venga eseguita.

avrei preferito andare per un'opzione dove ho avuto un processo separato, possibilmente un servizio di Windows, che otterrebbe le richieste di operazioni costose e di eseguire al di fuori del processo di asp.net. Ciò non solo significherebbe che la tua costosa operazione sopravviverebbe al riavvio del pool di applicazioni, ma semplificerebbe anche la tua applicazione web dal momento che non doveva gestire l'elaborazione.

Dire al servizio di eseguire il costoso processo potrebbe essere fatto utilizzando una sorta di comunicazione tra processi, il servizio potrebbe eseguire il polling di una tabella di database o di un file, oppure è possibile utilizzare una coda di gestione che il servizio dovrebbe ascoltare.

Ci sono molti modi per farlo, ma il mio punto principale è che dovresti separare il costoso processo dalla tua applicazione web se possibile.

1

a: sì.

Utilizzare il ThreadPool;) Coda un oggetto di lavoro - evita il sovraccarico di generazione di tonnellate di thread.

7

Si consiglia di utilizzare la classe BackgroundWorker anziché utilizzare direttamente i thread. Questo perché BackgroundWorker è progettato specificamente per eseguire operazioni in background per un'applicazione grafica e (tra le altre cose) fornisce meccanismi per comunicare gli aggiornamenti all'interfaccia utente.

+0

Ma '' BackgroundWorker' utilizza ThreadPool' discussioni, che non dovrebbero essere utilizzate per operazioni di lunga durata. – Toby

+0

Avete un riferimento per questo? –

+0

Dipende anche dalla definizione di "long-running". C'è una differenza tra "abbastanza a lungo non vogliamo far sedere e aspettare l'utente" e "ore o giorni". –