Kri*_*ekk 2 c# multithreading list windows-phone-7
为了提高WrapPanel的性能,我已经为我的WP7应用程序引入了线程.在一个列表中有很长List
的Item
对象,逐个添加到另一个列表中.我有以下两个清单:
public List<Item> OriginalItems;
public List<Item> CopyOfItems;
Run Code Online (Sandbox Code Playgroud)
放在BackgroundWorker.DoWork
事件处理程序中的逻辑如下:
workerThread.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e) =>
{
foreach (var item in OriginalItems)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
CopyOfItems.Add(item);
});
// I feel sooo sleepy
}
});
Run Code Online (Sandbox Code Playgroud)
现在,当我用Thread.Sleep(150)
- 替换我的注释时,这很好用- 但是任何更少(并且偶尔使用更大的值)会使代码连续多次放在同一个元素中.
这是为什么,以及如何解决?
这是C#中已知的皱纹 - 实际上是在C#5中修复的皱纹.当您从foreach
lambda表达式中的循环捕获循环变量时,您将捕获一个变量.该变量通过循环更改其值 - 因此,如果在"原始"迭代完成后执行从lambda表达式创建的委托,您将看到来自"当前"迭代的值.
一个简单的解决方法是在循环中声明和初始化迭代变量的副本,并捕获:
foreach (var item in OriginalItems)
{
var copy = item;
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
CopyOfItems.Add(copy);
});
// I feel sooo sleepy
}
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅Eric Lippert的博客文章"关闭循环变量被认为有害".
顺便说一下,你的真实代码是否真的在循环中做任何工作?除了将UI线程工作分成几个块之外,还不清楚你是否真的使用线程来做任何有意义的事情 - 这可以在没有的情况下完成BackgroundWorker
.