簡體   English   中英

Dispatcher.begin僅通過循環調用最后一次執行嗎?

[英]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”。

有關更多詳細信息,請閱讀Eric Lippert的博客文章“關閉認為有害的循環變量”-第一部分 第二部分

您正在關閉一個迭代變量。 解決方案是將loc分配給循環內的臨時變量。

    foreach (MapLocation location in e.Result)
    {
        //assign temp variable here.
        MapLocation loc = location;
        //...
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM