metodos instrucciones funciones expresiones delegados anonimos anonimas c# multithreading lambda anonymous-methods threadpool

c# - instrucciones - ThreadPool.QueueUserWorkItem con una expresión lambda y un método anónimo



instrucciones lambda c# (5)

Pasar dos parámetros a un nuevo hilo en la agrupación de hilos puede ser complicado, pero parece que con expresiones lambda y métodos anónimos, puedo hacer esto

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 }

Ahora, ciertamente he simplificado este ejemplo, pero estos puntos son clave:

  • Los objetos de cadena que se pasan son inmutables y, por lo tanto, a prueba de subprocesos.
  • Las variables s1 y s2 se declaran dentro del alcance del bloque try, que salgo inmediatamente después de poner en cola el trabajo en el grupo de hilos, por lo que las variables s1 y s2 nunca se modifican después de eso.

¿Hay algo malo con esto?

La alternativa es crear una nueva clase que implemente un tipo inmutable con 3 miembros: test, s1 y s2. Eso parece un trabajo extra sin beneficio en este punto.


Es una buena manera de hacerlo. No veo ninguna desventaja de usar lambdas. Es simple y limpio.


Lo que estás viendo se conoce como un cierre. Como dice chuckj , el compilador está generando una clase en tiempo de compilación que corresponde a los miembros a los que se accede fuera del cierre.

Lo único de lo que tiene que preocuparse es si tiene parámetros de referencia o de salida. Mientras que las cadenas son inmutables, las referencias a ellas (o cualquier variable) NO.


No hay nada malo en esto. El compilador esencialmente está haciendo automáticamente lo que describió como su alternativa. Crea una clase para contener las variables capturadas (prueba, s1 y s2) y pasa una instancia delegada a la lambda que se convierte en un método en la clase anónima. En otras palabras, si continuara con su alternativa, terminaría con algo muy similar a lo que el compilador acaba de generar para usted.


Para este ejemplo en particular, no hay nada malo aquí. El estado que ha pasado al otro subproceso está totalmente contenido y ninguno de los tipos implicados tiene problemas de afinidad de subprocesos.


Un problema potencial con el patrón es que es muy tentador expandirlo a algo más genérico pero menos seguro como este (código de memoria virtual, no espere que funcione):

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 } }