ThreadPool.QueueUserWorkItem con un'espressione lambda e metodo anonimo
-
09-09-2019 - |
Domanda
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:
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 chiave:
- Gli oggetti stringa trasmesse, sono immutabili e quindi threadsafe
- Le variabili S1 e S2 sono dichiarati nell'ambito di applicazione del blocco try, che esco subito dopo l'accodamento dei lavori al pool di thread, quindi le variabili S1 e S2 non sono mai modificato dopo che.
C'è qualcosa di sbagliato in questo?
L'alternativa è quella di creare una nuova classe che implementa un tipo immutabile, con 3 membri: prova, s1, s2 e. Questo sembra proprio come lavoro extra senza alcun beneficio a questo punto.
Soluzione
Non c'è niente di sbagliato in questo. Il compilatore è essenzialmente facendo automaticamente quello che hai descritto come alternativa. Si crea una classe per contenere le variabili acquisite (prova, S1 e S2) e passa un'istanza delegato al lambda che viene trasformato in un metodo sulla classe anonima. In altre parole, se si è andato avanti con la vostra alternativa si finirebbe con soemthing molto simile a quello che il compilatore appena generato per te.
Altri suggerimenti
Per questo particolare esempio, non v'è nulla di sbagliato qui. Lo stato di aver superato in altro thread è wholely contenuta e nessuno dei tipi di coinvolgere avere problemi filo di affinità.
E 'un bel modo di farlo. Non vedo alcun svantaggi di usare lambda. E 'semplice e pulito.
Quello che state osservando è riferito come una chiusura. Come chuckj stati , il compilatore sta generando una classe in fase di compilazione che corrisponde ai membri che sono accessibili all'esterno della chiusura.
L'unica cosa che si deve preoccupare è se si dispone di rif o parametri fuori. Mentre le stringhe sono immutabili, i riferimenti a loro (o qualsiasi variabile) non sono.
Un problema potenziale con il pattern è che è molto allettante per espanderlo in qualcosa di più generico, ma meno sicuri come questo (zero code-non aspettatevi di lavorare):
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
}
}