当我更新我的ObservableCollection时,GUI被冻结

时间:2010-10-21 10:31:17

标签: c# multithreading user-interface observablecollection freeze

我有一个显示ObservableCollection的WPF应用程序。它大约有182行,集合中的对象(我们称之为PositionLight)有大约70个要显示的属性。

在这些属性中输入数据的所有计算都在第二个线程中进行,该线程将每20秒重新计算一次,并将一个List发送到WPF窗口,thx到一个事件。这种方式计算不会减慢GUI。

将List中的ObservableCollection转换为与事件一起发送到GIU的EventArgs的构造函数。

问题是即使我使用BeginInvoke和委托来执行:

myGUICollection = myEventArgsCollection

GUI将被冻结3到4秒......我已经放了很多Console.Writeline来找出瓶颈在哪里,但看起来冻结将在它离开被调用的函数之后发生BeginInvoke。我真的迷失在这里。

我正在使用配备2.5Go RAM的4核PC,所以我认为这不是硬件问题。

你们有个主意吗?

一些代码可以让您更好地了解GUI中的插入内容:

    public bool myCoreScope_OnCoreCalculationHandler(object myObject, CoreCalculationEventArgs myEventArgs)
    {

        foreach (PositionLight item in myEventArgs.MyPositionList)
        {
            lv.Dispatcher.BeginInvoke(new DisplayPositionItemCallBack(DisplayPositionItem), DispatcherPriority.Send, new object[] { item });
        }

    }


    private delegate void DisplayPositionItemCallBack(PositionLight item);

    private void DisplayPositionItem(PositionLight item)
    {
        try
        {
           MyPositionList.Remove(MyPositionList.First(position => position.ID== item.ID));
        }
        catch (Exception)
        { }
        MyPositionList.Add(item);
    }

1 个答案:

答案 0 :(得分:2)

当您调用BeginInvoke时,您正在将ObservableCollection的更新编组到GUI线程上,因此虽然计算可能发生在单独的线程上,但UI的更新却没有。如果在GUI线程上调用昂贵的更新,则线程必须等到该操作完成。

另一种方法是对集合中的每个项目执行调用,而不是立即对整个集合执行调用,这将使GUI有时间在更新之间处理其他消息。

var list = GetCollection();
foreach (var item in list)
{
    Dispatcher.BeginInvoke(new Action(() => myGuiCollection.Add(item)));
}

您可以尝试的另一个选项是设置ItemsSource数据绑定的IsAsync属性。

<ListBox ItemsSource="{Binding myGuiCollection, IsAsync=True}" />