views:

58

answers:

1

In Windows Phone 7 / Silverlight, is the following code safe or is it a race condition?

//Snippet 1
foreach(var item in list)
{
   Deployment.Current.Dispatcher.BeginInvoke( () => { foo(item); });
}

Surely (?) this alternative is racy?

//Snippet 2
Deployment.Current.Dispatcher.BeginInvoke( () => 
   { 
       foreach(var item in list){ foo(item); }
   });
list.Clear();
+5  A: 

"Race condition" may not be the best way to put the problem with the first snippet. But basically, you are using a captured variable outside the capture scope. The value of "item" will end up being the last item then your foo method is called, for all items.

Instead, do this:

foreach(var item in list)
{
   var tmpItem = item;
   Deployment.Current.Dispatcher.BeginInvoke( () => foo(tmpItem));
}

This puts a variable in a lower scope, and it is captured in that scope. This makes sure that each value is captured and sent to foo.

The second version is almost certainly an error given a sane scope of the list variable.

Philip Rieck
Can you clarify "The value of "item" will end up being the last item then your foo method is called, for all items."? Are you saying that in the first snippet, foo() _will_ be called for all item values in list, but in reverse order (i.e., stack-like)?
Larry OBrien
No. What Philip is saying is that foo() will be called the proper number of times, but the item value passed to it will likely be the last item in the list for each iteration.
ctacke
Thank you. That's the behavior that I originally suspected would result.
Larry OBrien