Lambda expressions, captured variables and threading Lambda expressions, captured variables and threading multithreading multithreading

Lambda expressions, captured variables and threading


I think in your first example., you mean

QueueUserWorkItem( () => SendMessage(message) );

In your second item, where does the parameter s come from? I think you mean

QueueUserWorkItem( s => {SendMessage((string)s);} , message );

Now, these two both work equivalently, but

  • In the first case: the parametermessage is copied from the scope ofthis DoStuff method and storeddirectly in your lambda expressionitself, as a closure. The lambda haskeeps a copy of message.

  • In the second case: message is sentto the Queue, and the queue keepshold of it (along with the lambda),until the lambda is called. It ispassed at the time of running thelambda, to the lambda.

I would argue that the second case is more programmatically flexible, as it could theoretically allow you to later change the value of the message parameter before the lambda is called. However the first method is easier to read and is more immune to side-effects. But in practice, both work.


For your example (a reference to an immutable string object) it makes absolutely no difference.

And in general, making a copy of a reference is not going to make much difference. It does matter when working with value types:

 double value = 0.1; ThreadPool.QueueUserWorkItem( () => value = Process(value)); // use captured variable // -- OR -- ThreadPool.QueueUserWorkItem( () =>      {           double val = value;      // use explicit parameter           val = Process(val);      // value is not changed      });  // -- OR -- ThreadPool.QueueUserWorkItem( (v) =>      {           double val = (double)v;  // explicit var for casting           val = Process(val);      // value is not changed      }, value); 

The first version is not thread-safe, the second and third might be.

The last version uses the object state parameter which is a Fx2 (pre-LINQ) feature.


  1. If you want the anonymous functors reference the same state, capture a identifier from common context.
  2. If you want stateless lambdas (as I would recommend in a concurrent application) use local copies.