GUI frozen while i update my ObservableCollection
I have a WPF application that displays an ObservableCollection. It's about 182 rows, and the object (let's call it PositionLight) inside the collection has about 70 properties to display.
All calculation to input开发者_如何学Go data in these properties are made in a second thread which will recalc everything every 20 secondes, and will send a List to the WPF window, thx to an Event. This way calculation doesn't slow down the GUI.
the List is transformed in an ObservableCollection in the constructor of the EventArgs sent with the event to the GIU.
The problem is even when i use a BeginInvoke and a delegate to do:
myGUICollection = myEventArgsCollection
the GUI will be frozen for 3 to 4 seconds... I've put a lot of Console.Writeline to find out where is the bottleneck, but it looks like the freeze will occurs just after it leaves the function called by the BeginInvoke. I'm really lost here.
I'm using a 4 core PC with 2.5Go RAM, so i don't think this is a hardware problem.
Do you guys have an idea?
Some code to give you a better idea of the insert in the 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);
}
When you call BeginInvoke you are marshalling the update of the ObservableCollection onto the GUI thread, so while the calculation may happen on a seperate thread the update of the UI does not. If you invoke an expensive update onto the GUI thread, then the thread will have to wait until that operation is completed.
An alternative approach is to perform an invoke for each item in the collection, rather than the whole collection at once, which will give the GUI time to process its other messages between updates.
var list = GetCollection();
foreach (var item in list)
{
Dispatcher.BeginInvoke(new Action(() => myGuiCollection.Add(item)));
}
Another option you could try is to set the IsAsync
attribute of the ItemsSource data-binding.
<ListBox ItemsSource="{Binding myGuiCollection, IsAsync=True}" />
精彩评论