我有一个显示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);
}
答案 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}" />