[英]Dispatcher.beginInvoke only executing the last time through a loop?
我在Silverlight代碼中有一段代碼,看起來像這樣:
foreach (MapLocation loc in e.Result)
{
testDict[loc.ElemId] = loc.ToString();
this.Dispatcher.BeginInvoke(delegate()
{
Image icon = new Image();
icon.SetValue(Image.SourceProperty, nurseIconSource);
Canvas.SetLeft(icon, (double)loc.X * MAP_SCALE);
Canvas.SetTop(icon, MAP_HEIGHT - (double)loc.Y * MAP_SCALE);
icons[loc.ElemId] = icon;
MainCanvas.Children.Add(icon);
});
}
}
此循環在與UI線程分開的線程上運行25次。 執行該方法后,testDict對象最終包含所有25個條目,而圖標字典僅存儲第25個(最后一個)項目的條目。
這是我第一次使用Dispatcher。 難道不應該被稱為“速射”嗎? 我能想到的是,第一次調用委托是在循環的最后一次之后,因此loc對象始終是同一項目。 這個准確嗎?
這是古老的“不捕獲循環變量”問題。 這吸引了很多人。
基本上,當委托執行時,它總是使用loc
的當前值...並且,如果您在委托執行之前已經完成了循環,那么這基本上意味着loc
的最后一個值會顯示多次。
解決方案是復制循環變量:
foreach (MapLocation loc in e.Result)
{
MapLocation copy = loc;
testDict[loc.ElemId] = loc.ToString();
this.Dispatcher.BeginInvoke(delegate()
{
Image icon = new Image();
icon.SetValue(Image.SourceProperty, nurseIconSource);
Canvas.SetLeft(icon, (double)copy.X * MAP_SCALE);
Canvas.SetTop(icon, MAP_HEIGHT - (double)copy.Y * MAP_SCALE);
icons[copy.ElemId] = icon;
MainCanvas.Children.Add(icon);
});
}
注意匿名方法中使用“ copy”而不是“ loc”。
您正在關閉一個迭代變量。 解決方案是將loc分配給循環內的臨時變量。
foreach (MapLocation location in e.Result)
{
//assign temp variable here.
MapLocation loc = location;
//...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.