2009-04-10 8 views
23

passando due parametri per un nuovo thread sul ThreadPool a volte può essere complicato, ma sembra che con le espressioni lambda e metodi anonimi, posso fare questo:ThreadPool.QueueUserWorkItem con un'espressione lambda e metodo anonimo

public class TestClass 
{ 
    public void DoWork(string s1, string s2) 
    { 
     Console.WriteLine(s1); 
     Console.WriteLine(s2); 
    } 
} 

try 
{ 
    TestClass test = new TestClass(); 
    string s1 = "Hello"; 
    string s2 = "World"; 
    ThreadPool.QueueUserWorkItem(
     o => test.DoWork(s1, s2) 
     ); 
} 
catch (Exception ex) 
{ 
    //exception logic 
} 

Ora, ho certamente semplificato questo esempio, ma questi punti sono fondamentali:

  • Gli oggetti stringa trasmesse, sono immutabili e quindi threadsafe
  • Il s1 e s2 variabili sono dichiarate w Nell'ambito del blocco try, che esco subito dopo aver accodato il lavoro al pool di thread, quindi le variabili s1 e s2 non vengono mai modificate successivamente.

C'è qualcosa di sbagliato in questo?

L'alternativa è creare una nuova classe che implementa un tipo immutabile con 3 membri: test, s1 e s2. Sembra solo un lavoro extra senza alcun beneficio a questo punto.

+1

Perché non scrivi semplicemente 'o => test.DoWork (s1, s2)' invece della definizione più dettagliata? –

+0

@ Mehrdad: Perché sono davvero nuovo per le espressioni lambda. ;) - Grazie! –

+0

@ Mehrdad: l'ho modificato nella domanda. –

risposta

16

Non c'è niente di sbagliato in questo. Il compilatore sta essenzialmente facendo automaticamente ciò che hai descritto come alternativa. Crea una classe per contenere le variabili catturate (test, s1 e s2) e passa un'istanza delegata al lambda che viene trasformato in un metodo sulla classe anonima. In altre parole, se avanzi con la tua alternativa, ti ritroverai con qualcosa di molto simile a quello che il compilatore ha appena generato per te.

2

È un bel modo di farlo. Non vedo alcun svantaggio dell'uso di lambda. È semplice e pulito.

4

Per questo particolare esempio, non c'è niente di sbagliato qui. Lo stato che hai passato nell'altro thread è completamente contenuto e nessuno dei tipi coinvolge problemi di affinità di thread.

+0

E il modello generale, allora? Come sarebbe sapere se un tipo ha problemi di affinità di thread? –

+0

Fondamentalmente ti stai chiedendo se una classe è protetta da thread o meno. Nella mia particolare implementazione (nella maggior parte dei casi) utilizzo oggetti profondamente immutabili per renderli a prova di thread. Altri modi per rendere gli oggetti a prova di codice è utilizzare il blocco, ecc. –

+0

@Joel se un tipo presenta problemi di affinità del thread, si è brindati. Non puoi fare nulla con esso su un thread separato. Lo schema generale è valido (lo uso spesso) – JaredPar

2

Quello che stai vedendo è indicato come una chiusura. Come chuckj states, il compilatore sta generando una classe in fase di compilazione che corrisponde ai membri a cui si accede al di fuori della chiusura.

L'unica cosa di cui ti devi preoccupare è se disponi di parametri di riferimento. Mentre le stringhe sono immutabili, i riferimenti a esse (o qualsiasi variabile) NON sono.

1

Un problema potenziale con il modello è che è molto allettante per espanderlo in qualcosa di più generico, ma meno sicuri come questo (zero code-non aspettatevi che funzioni):

public static void QueueTwoParameterWorkItem<T1, T2>(T1 value1, T2 value2, workDelegate<T1,T2> work) 
{ 
    try 
    { 
     T1 param1 = value1; 
     T2 param2 = value2; 
     ThreadPool.QueueUserWorkItem(
      (o) => 
      { 
       work(param1, param2); 
      }); 
    } 
    catch (Exception ex) 
    { 
     //exception logic 
    } 
} 
+0

Nel mio caso, ho una classe base profondamente immutabile che potrei usare per inchiodare T1 e T2 ... in modo che tu possa fare questo lavoro nel mio caso specifico. Se non si capiscono i problemi di threading, allora usare il threadpool è fuori questione comunque. –

+0

concordato: il tuo caso specifico va bene. È quando lo si implementa come un modello generico ci sono preoccupazioni. –