In order to up performance on a WrapPanel, I have introduced threading to my WP7 app. There’s a long List of Item-objects in one list, that one by one is added to another `List. I have the following two lists:
public List<Item> OriginalItems;
public List<Item> CopyOfItems;
The logic that’s put inside the BackgroundWorker.DoWork event handler is as follows:
workerThread.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e) =>
{
foreach (var item in OriginalItems)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
CopyOfItems.Add(item);
});
// I feel sooo sleepy
}
});
Now, this works just fine when I replace my comment with Thread.Sleep(150) – but anything less (and every once in a while even with larger values) makes the code put in the same element several times in a row.
Why is this, and how can it be fixed?
This is a known wrinkle in C# – and actually one which is being fixed in C# 5. When you capture the loop variable from a
foreachloop in a lambda expression, you’re capturing one variable. That variable changes its value through the loop – so if you execute the delegate created from the lambda expression after the “original” iteration as completed, you’ll see the value from the “current” iteration instead.A simple work around is to declare and initialize a copy of the iteration variable in the loop, and capture that:
See Eric Lippert’s blog post “Closing over the loop variable considered harmful” for more details on this.
Does your real code actually do any work in the loop, by the way? It’s not clear that you’re really using threading to do anything significant other than splitting the UI thread work into several chunks – which can be done without a
BackgroundWorker.