none
Why is copying 10 items to an observable collection so slow and how to speed up? RRS feed

  • Question

  • This code operates in a .NET WPF C# environment. The basic code creates a collection of about 10 objects. The collection is sorted and then copied. When the copy happens the time to execute adds an astonishing 7 seconds. The observable collection does not have any subscribers at this point so one would not expect any time to be lost due to broadcast change notifications.

    The application is based on a WinForm used to create a System Tray Notification item. When the tray icon is clicked upon a WPF window is shown. At the time that the WPF window becomes visible a DispatcherTimer is created and started. A short delay after that and a web service call is made which collects information which is written into userItems, a local variable. This collection will be passed back to the caller who will put it into a class property that will be bound to the source for a ComboBox. This code works well and fast. There is a problem with it, however, in that the contents of the ComboBox drop down list are not sorted. I thought that it would be trivial to handle that by sorting the contents of the userItems before it is passed back to the caller. Not so, sneaker breath. Here's the important part of the code:

    // A local variable is declared.
    ObservableCollection<UserItem> userItems = null;

    // Snipped from the code is the initial population of userItems.

    // A sorted copy of userItems is created. This is quick.
    List<UserItem> lui = userItems.OrderBy( a => a.user_id ).ToList();

    // The original collection is emptied so that it can be populated with the
    // sorted elements.
    userItems.Clear();

    // The sorted list of items, only about 10 objects, is copied back to userItems.
    // This is where the time is being spent, an astonishing 7 seconds to copy 10 items.
    // If the copy is commented out then the code runs in almost no time at all.
    for (int x = 0; x < lui.Count; x++)     userItems.Add( lui[x] );

    Any ideas why the above code fragment runs so slowly and how can I speed it up?


    Richard Lewis Haggard


    • Edited by Richard.Haggard Wednesday, January 16, 2019 9:23 PM Was asked for more info
    Wednesday, January 16, 2019 7:59 PM

All replies

  • Hi,

    have you tried this:

    ObservableCollection<UserItem> userItems = new ObservableCollection<UserItem>(lui);

    Greetings, Chris

    Wednesday, January 16, 2019 8:24 PM
  • No change. Still takes an unreasonable amount of time to complete the operation.

    Richard Lewis Haggard

    Wednesday, January 16, 2019 8:53 PM
  • Can you show us the code of UserItem, please? Maybe it's possible to reproduce the behavior.
    Wednesday, January 16, 2019 9:06 PM
  • Because of the NDA, the real source cannot be supplied. The original question was modified so as to contain more background info, the condensed version goes like this:

    A WinForm SysTray icon is clicked.

    A WPF Window is displayed.

    The WPF window starts a DispatcherTimer.

    The alarm callback happens.

    Information is collected from a web service.

    The information is used to populate userItems.

    userItems is copied to another collection and sorted.

    All of the above runs as expected.

    The slow part is when userItems is repopulated with the sorted contents.


    Richard Lewis Haggard

    Wednesday, January 16, 2019 9:27 PM
  • ...

    The information is used to populate userItems.

    userItems is copied to another collection and sorted.

    ...

    Is this necessary? Is it not better to populate another collection, sort it and copy it to userItems?
    Wednesday, January 16, 2019 9:56 PM
  • Hi Richard.Haggard,

    Thank you for posting here.

    Further to your issue, you want to improve the efficiency of the for statement.

    You could try the parallel.for method to make it, please try the following code.

    Parallel.For(0, lui.Count, (i) =>
                {
                    userItems.Add(lui[i]);
                });
    
    

    Hope my advice could be helpful.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, January 18, 2019 9:56 AM
    Moderator
  • Try dividing it into two operations like this;

    List<UserItem> luiTemp  =  userItems.ToList();

    List<UserItem> lui = luiTemp.OrderBy( a => a.user_id ).ToList();

    userItems.Clear();


    for (int x = 0; x < lui.Count; x++)     userItems.Add( lui[x] );


    Then the heavy work is done on a list and not on an observable collection
    Sunday, January 20, 2019 7:48 AM