Dispatcher.BeginInvoke lambda capture thread-safe?
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();
"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.
精彩评论