LP on .NET

May 18, 2010

Don’t Fall into the Outer Variable Trap

Filed under: .NET,C#,LINQ,Software Development — Larry Parker @ 9:54 pm

Today I needed to loop through a collection and call a method on each of its items.  This was inside a service call that needed to return quickly, which meant that the methods would be called asynchronously.

So I queued up the tasks on the thread pool and was done:

foreach (Manager mgr in ManagerList)
    ThreadPool.QueueUserWorkItem(o => mgr.DoIt());

Very simple.

But when I ran it, I found that the DoIt method was only called on the last item in the list and was called repetitively (once for each item in the collection).

What happened here?  The code looks like it should work!

This is a common pitfall when using outer variables and is sometimes referred to as the “outer variable trap”.

The problem here is that there’s actually a race condition since the value of the outer variable “mgr” is important at the time the work item is actually executed.

The reason the behavior is erratic is because “mgr” is an outer variable referred to by the lambda expression passed to QueueUserWorkItem, but when the lambda expression is actually evaluated the value of mgr may have changed.

So instead of relying on an outer variable and lucky timing, the correct approach is to pass the outer variable into QueueUserWorkItem and then have the lambda expression call the DoIt method on its local variable.

foreach (Manager mgr in ManagerList)
    ThreadPool.QueueUserWorkItem(o => (o as Manager).DoIt(), mgr);

This works because “mgr” is passed into QueueUserWorkItem and is exactly what the local variable “o” inside the lambda expression refers to.  We need to cast it to the Manager class because QueueUserWorkItem’s WaitCallback delegate uses an Object in its signature.

So be careful of outer variable semantics and avoid the trap.  They can cause lots of trouble because you may think your code will run a certain way but in actuality it could be doing something very different.

Hope this helps.

Blog at WordPress.com.