2

我有一个WPF应用程序,显示一个ObservableCollection。它大约有182行,集合中的对象(我们称之为PositionLight)有大约70个属性可以显示。GUI冻结,而我更新我的ObservableCollection

所有计算这些性质的输入数据在第二个线程将重计算的一切,每20个secondes,并将列表发送到WPF窗口,THX一个事件制成。这种计算不会减慢GUI。

这份名单是在与该事件的GIU发送的EventArgs的构造一个ObservableCollection转化。

的问题是,即使我使用的BeginInvoke和委托办:

myGUICollection = myEventArgsCollection

的图形用户界面将被冻结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); 
    } 
+0

发布一些更多的代码来分析 – TalentTuner 2010-10-21 10:39:15

+0

@saurabh:done。我考虑了Fara所说的,但仍然以相同的冻结时间结束 – Gregfr 2010-10-22 04:00:09

回答

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}" /> 
+0

你说的确实有道理,但是,逐项添加项目意味着我首先找到旧项目,将其删除,然后添加新项目一。恐怕不会加速这个过程。无论如何,我会试试 – Gregfr 2010-10-22 02:27:03

+0

GOT IT!我没有删除和插入新项目,而是逐个更新evry现有项目。它看起来像这样使用更少的CPU,并且GUI不再被冻结。我会让话题开放几个小时,以确认它正常工作 – Gregfr 2010-10-22 06:30:04

+0

好的,我正在考虑更多关于初始化集合,而不是更新它。为了更新绑定到UI的东西,你应该看看INotifyPropertyChanged接口。这是做这种事情的最佳方式。 – 2010-10-22 09:44:20