Posts Tagged C#
Why lambdas seem broken in multithreaded environments (or how closures in C# works).
Posted by Patrik Löwendahl in Code Design on April 20, 2010
I’ve been playing around with some code for.NET 3.5 to enable us to split big operations into small parallel tasks. During this work I was reminded why Resharper has the “Access to modified closure” warning. This warning tells us about a inconsistency in handling the ”Immutable” loop variable created in a foreach loop when lambdas or anonymous delegates are involved.
Take this code:
public static void ForEach(IEnumerable list) { foreach(var item in list) { Action action = () => Console.WriteLine(item); action.Invoke(); } }
This will yield the expected result. When we call WriteLine the current item will be displayed:
A naïve and not so interesting example, but creates a baseline. Now let’s look at the real code where the reminder was at, a mimic of .NET 4’s parallel foreach:
public static void ForEach(IEnumerable list, Action task) { var waitHandles = new ManualResetEvent[list.Count()]; var index = 0; foreach(var item in list) { var handleForCurrentTask = new ManualResetEvent(false); waitHandles[index] = handleForCurrentTask; ThreadPool.QueueUserWorkItem(delegate { task(item); handleForCurrentTask.Set(); }); index++; } WaitHandle.WaitAll(waitHandles); }
Calling this with the following line:
ForEach(items, Console.WriteLine);
Will give a more unexpected result (if you don’t know what’s going on that is).
So what is going on, or how closures are implemented in C#.
To understand the issue we must examine how the C# compiler handles anonymous delegates and lambdas (called lambda from now on). Since they are really a compiler trick and not a real feature of the Common Language Runtime.
For every lambda we define; the compiler will generate a new method (there are some nice tricks to avoid duplication but for the sake of this post let’s go with this simple definition). As illustrated in this screenshot from Reflector:
As you can see this is encapsulated inside an auto generated class. That class also contains a couple of instances variables that we’ll discuss.
We can see that the method encapsulated the two lines of code we had inside our lambda and has a dependency on “task” and “item” from instance variables that are also auto generated types.
To be able to execute the Foreach method in the auto generated class, we’ll need to initialize the instance variables of the lambda class. The compiler neatly picks this up and creates a couple lines of code in the beginning of the method to encapsulate Task:
public static void ForEach(IEnumerable list, Action task) { <>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1 (); CS$<>8__locals2.task = task;
A bit further down in the method we can see how the the item variable is encapsulated inside another auto generated instance variable.
<>c__DisplayClass3CS$<>8__locals4 = new <>c__DisplayClass3 (); while (CS$5$0000.MoveNext()) { CS$<>8__locals4.item = CS$5$0000.Current;
Notice how the creation of the object that encapsulates the item is declared outside of the iteration and the item is then passed into the object inside of the iteration. Here is the heart of the problem. In the interest of optimization, the compiler encapsulates parameters and variables as few times as possible. It seems like the optimizer do not recognize the immutable nature of the loop variable, nor the perceived local scope of it.
Further down this is passed into the ThreadPool as a delegate:
<>c__DisplayClass5CS$<>8__locals6 = new <>c__DisplayClass5 (); CS$<>8__locals6.CS$<>8__locals4 = CS$<>8__locals4; CS$<>8__locals6.CS$<>8__locals2 = CS$<>8__locals2; CS$<>8__locals6.handleForCurrentTask = new ManualResetEvent(false); waitHandles[index] = CS$<>8__locals6.handleForCurrentTask; ThreadPool.QueueUserWorkItem(new WaitCallback(CS$<>8__locals6. b__0));
So while the delegate that is passed to the thread pool is instantiated for each iteration, the variables and parameters used by the closure isn’t.
In a scenario where the lambda is executed inside the loop this will not be a problem, the next time the item variable is assigned, the previous execution will already be done. In a multithreaded, or a deferred execution of the lambda the story is quite different.
The assignment of the Item variable is far from safe here. Since the reference to the item encapsulation will be shared between all of the instances of the delegate passed to the ThreadPool. Thus they will share the last (or the last at the time of execution) assignment.
To solve this we need to tell the compiler that the Item variable is locally scoped to the loop and not a method-wide variable.
A simple change to:
foreach(var item in list) { var handleForCurrentTask = new ManualResetEvent(false); waitHandles[index] = handleForCurrentTask; var currentItem = item; ThreadPool.QueueUserWorkItem(delegate { task(currentItem); handleForCurrentTask.Set(); });
Will be enough for the compiler do do the right thing. It will now move Item inside the closure class for the lambda and not create a separate class:
Since this class had an instance created for each iteration, we will now have a separate copy of the item value in each delegate passed to the ThreadPool:
<>c__DisplayClass3CS$<>8__locals4 = new <>c__DisplayClass3 (); CS$<>8__locals4.CS$<>8__locals2 = CS$<>8__locals2; CS$<>8__locals4.handleForCurrentTask = new ManualResetEvent(false); waitHandles[index] = CS$<>8__locals4.handleForCurrentTask; CS$<>8__locals4.currentItem = item; ThreadPool.QueueUserWorkItem(new WaitCallback(CS$<>8__locals4. b__0));
And we’ll get the expected result again:
In conclusion
Most people will not run into this problem, but it is an interesting one never the less. I would argue that for deferred executed lambdas, the semantics of foreach is not the same as it is for the rest of the language. I’m sure the C# team has a really good reason for ignoring that Item really should be handled as a locally scoped variable, but my brain isn’t big enough to figure that out at the moment.
Maybe some of you know?
3 Comments
Slice up your business logic using C# Extension methods to honor the context
Posted by Patrik Löwendahl in Architecture, design patterns on February 20, 2010
One of my favorite features with C# 3.0 is the extension methods. An excellent way to apply some cross cutting concerns and great tool for attaching utility functions. Heavily used by the LINQ frameworks and in most utility classes I’ve seen around .NET 3.5 projects. Some common example usages I’ve come across include:
1: var name = "OlympicGames2010".Wordify();
2: var attributeValue = typeof(Customer).Attribute(o => o.Status)
3: .Value();
Lately I’ve started to expand the the modeling ideas I tried to explain during my presentation at Öredev 2008. It became more of a discussion with James O. Coplien then a presentation and I was far from done with my own understanding of the ideas and issues I’d identified (there are things improve in this content). The core idea is pretty simple though:
Not all consumers of an object are interested of the same aspects of that object, it will take on different roles in different contexts
Let me explain with the simplest example; when building an order system, the aspects of a product that the order think is important are usually not exactly the same aspects that the inventory system value.
Contexts in object models
Eric Evans touches this in his description of “bounded contexts” (Domain Driven Design p335) where he stresses the importance of defining contexts where a model is valid and not mix it into another context. In essence the model of a product should be duplicated, once in the order context and once in the inventory context.
This is a great principle but at times it be too coarse-grained. James Coplien and Trygve Reenskaug have identified this in their work around, what they call, “DCI architecture”. Richard Öberg et al have done some work in what they call qi4j where they are composing objects with bits and pieces instead of creating full blown models for each context.
Slicing logic and models using Extension Methods
Let’s get back to the extension methods and see how they can help us slice business logic up in bits and pieces and “compose” what we need for different contexts.
In the code base I’m writing for my TechDays presentation I have a warehouse class that holds stock of items. These Items are common for different contexts, they will surface in orders and PLM. One of the features in this application is to find a stock to reserve a given an item. The following code is used to find that stock:
1: return Stock.First(stock => stock.Item == item);
Although trivial, this is a business rule for the warehouse. When the warehouse class evolved this piece of rule would be duplicated in methods like Reserve, Releaes and Delete. A classic refactoring would be to use Extract Method to move it out and reuse that piece, something like:
1: private bool Match(Stock stock, ItemInfo item)
2: {
3: return stock.Item == item
4: }
5: ...
6: return Stock.First(stock => Match(stock, item));
This is a completely valid refactoring but honestly we loose some intent, the immediate connection with stock and item are not as explicit and the lambda expression wasn’t simplified that much.
So let’s Refator to Slice instead:
1: public static class ItemInAWarehouseSlices
2: {
3: public static bool Match(this ItemInfo @this, Stock stock)
4: {
5: return stock.Item == @this;
6: }
7: }
Adding this business rules as an extension method gives us a natural place for the code to live and a mechanism to use to compose objects differently in different contexts. Importing this extension method class into the Warehouse C#-file, ItemInfo will provide the logic needed in that context;
1: return Stock.First(item.Match);
Adding the rule this way also sprinkles a touch of DSL on it and gives it a semantic meaning which makes the code make more sense.
Why don’t you just put that method on the ItemInfo, you migh ask. Well the answer is simple. ItemInfo is a concept that might be shared across contexts. Contexts that have no grasp of what a Stock is, nor should it. If I’d add everything I needed to the ItemInfo class for all contexts that uses Item. I would be in a bad shape. Thus the ideas behind Contextual Domain models, Bounded Context, DCI and Composite objects.
Extend away …
So extension methods have other usages then just extending existing classes with some utility. It’s also a powerful tool to slice your logic in composable pieces which helps you focus on the aspects you think is important in the current context you are working.
So what do you think? Will this help you create clear separtions?