2012-07-13 21 views
7

Sostituzione di thread (non ThreadPool Thread) con delegati asincroni (callback).Delegati asincroni vs thread

Il mio scenario: generare un thread/del.beginInvoke() per client.

Secondo me,

Motivi

  1. necessità di notifica tramite richiamata/Call delegato di nuovo richiamata
  2. evitare un sovraccarico Filo, (delegati utilizzano filo di thread)
  3. Passaggio di argomenti (Evita Casting to object) e necessitano di un valore di ritorno dal metodo.

Correggimi se sopra ragioni sono sbagliate.

  1. Sono altri motivi?
  2. Quale scenario ho esattamente bisogno di fare qualcosa con i delegati asincroni che i thread non possono?
    3.Performance?

Esempio

public delegate void SendCallbackType(); 

    SendCallbackType senderdel= new SendCallbackType(SendData); 

    public void StartSend() // This method Could be Called more than 700 times (Thread per Client) 
    { 
     senderdel.BeginInvoke(SendCallback,null); 
        // (or) 
     Thread t = new Thread(new ThreadStart(ThreadSend)); 
     t.IsBackground = true; 
     t.Start(); 
    } 

    //Async Delegate 
    void SendData() 
    { 
     string data = QueData.DeQueue(); 
     RaiseOnData(data); // Raise to event. 
    } 
    void SendCallback(IAsyncResult ar) 
    { 
     senderdel.BeginInvoke(SendCallback, null); 
    } 

//Thread 
    void ThreadSend() 
    { 
     while (true) 
     { 
     string data = QueData.DeQueue(); 
     RaiseOnData(data); // Raise to event. 
     } 
    } 

Da quanto sopra quale opzione sarebbe la migliore. Prestazione ?

risposta

10

Il tuo ragionamento è corretto. I delegati asincroni utilizzano thread dal pool di thread in modo che dovrebbero essere più veloci rispetto alla creazione di thread manuale. Fai attenzione però con questo nelle applicazioni ASP.NET. Poiché si consumano i thread di lavoro normalmente utilizzati da ASP.NET per le richieste di assistenza e l'applicazione potrebbe esaurire rapidamente le funzionalità di manutenzione.

I delegati asincroni vanno bene per le attività a uso intensivo della CPU. Per le attività intensive di I/O (come la lettura di flussi, chiamate di database e chiamate di servizi Web) è necessario utilizzare i metodi BeginXXX, EndXXX offerti direttamente dalle classi corrispondenti (Stream, SqlConnection, WebClient, ...). In questo modo non si sta utilizzando alcun thread durante la lunga operazione di I/O. Si utilizza I/O Completion Ports che è la cosa migliore in termini di attività associate I/O. Saranno ordini di grandezza più performanti e meno costosi di qualsiasi thread e pool di thread.

Quindi, per riassumere:

  • Per le attività ad alta intensità I/O Usare I/Completamento O Ports. Se l'attività intensiva di I/O è racchiusa in una libreria scritta male che non offre questa possibilità, utilizzare la TPL introdotta in .NET 4.0.
  • Per le attività a uso intensivo della CPU, utilizzare il TPL introdotto in .NET 4.0.

E se non si dispone di .NET 4.0 utilizzare il pool di thread a meno che non si stia scrivendo un'applicazione ASP.NET, nel qual caso si potrebbe ricorrere alla creazione manuale del thread.

In generale, è buona norma iniziare a utilizzare TPL e orientare i metodi come attività in modo da essere pronti per .NET 4.5 che introduce le parole chiave asincrone/attese.

+0

@ Darin: Grazie per la risposta.Qui il caso è l'applicazione Windows, penso che le attività puramente intensi della CPU, per quanto riguarda le prestazioni mentre si generano 1000 thread vs 1000 del.begininvoke() chiamano –

+0

@MSK, in questo caso si consiglia di utilizzare TPL e se si utilizza una versione precedente di. NET usa il pool di thread (ThreadPool, BackgroundWorker, Async delegates, ... => finiranno comunque al ThreadPool). Non generare i thread manualmente in questa situazione. –

+0

@ Darin: E non ho bisogno del fuoco e dimentico. Qui ho bisogno di un thread dedicato per dequeue (indipendentemente da ThreadPool) e allo stesso tempo è un processo a lunga esecuzione. –