Solved

Why does "Automatic Column Sorting Using LiNQ" solution appear so slow ???

Posted on 2013-06-06
2
780 Views
Last Modified: 2013-06-06
I have implemented the Assisted solution  ID: 37302780  proposed in the thread Automatic Column Sorting using LiNQ in C# (ID 27396517)

It works, but I was wondering why the sorting of the dataGridView appears so slow ?!?!

(~12 seconds to sort a List containing only 200 items !!!!!)

I changed a bit the proposed code expecting a faster sorting by suppressing the need to call the Find method in the for loop of the ApplySortCore overridden method.

Here is my AdvancedList modified code: (The overridden ApplySortCore method has been modified)

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

namespace SortedList
{

    public class AdvancedList<T> : BindingList<T>
    {

        protected override bool SupportsSearchingCore
        {
            get
            {
                return true;
            }
        }

        protected override bool SupportsSortingCore
        {
            get
            {
                return true;
            }
        }

        bool isSortedValue;
        protected override bool IsSortedCore
        {
            get
            {
                return isSortedValue;
            }
        }

        private ArrayList sortedList;
        private ArrayList unsortedItems;

        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            sortedList = new ArrayList();

            // Check to see if the property type we are sorting by implements
            // the IComparable interface.
            Type interfaceType = prop.PropertyType.GetInterface("IComparable");

            if (interfaceType == null && prop.PropertyType.IsValueType)
            {
                Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
                // Nullable.GetUnderlyingType only returns a non-null value if the    
                // supplied type was indeed a nullable type.     
                if (underlyingType != null)
                    interfaceType = underlyingType.GetInterface("IComparable");
            }

            if (interfaceType != null)
            {
                unsortedItems = new ArrayList(this.Count);

                // Loop through each item, adding it the the sortedItems ArrayList.
                int idx = 0;
                foreach (Object item in this.Items)
                {
                    sortedList.Add(new SortedItem { val = (IComparable)(prop.GetValue(item)), pos = idx});
                    unsortedItems.Add(item);
                    idx++;
                }
                // Call Sort on the ArrayList.
                sortedList.Sort();

                // Check the sort direction and then copy the sorted items
                // back into the list.
                if (direction == ListSortDirection.Descending)
                    sortedList.Reverse();

                for (int i = 0; i < this.Count; i++)
                {
                    int position = ((SortedItem)sortedList[i]).pos;
                    this[i] = (T)unsortedItems[position];
                }
                isSortedValue = true;

                // If so, set the SortPropertyValue and SortDirectionValue.
                sortPropertyValue = prop;
                sortDirectionValue = direction;

                // Raise the ListChanged event so bound controls refresh their
                // values.
                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, 1));

            }
            else
            {
                // If the property type does not implement IComparable, let the user
                // know.
                throw new NotSupportedException("Cannot sort by " + prop.Name +
                    ". This" + prop.PropertyType.ToString() +
                    " does not implement IComparable");
            }

        }

        ListSortDirection sortDirectionValue;
        PropertyDescriptor sortPropertyValue;
        protected override PropertyDescriptor SortPropertyCore
        {
            get { return sortPropertyValue; }
        }

        protected override ListSortDirection SortDirectionCore
        {
            get { return sortDirectionValue; }
        }

    }

    internal class SortedItem : IComparable
    {
        public IComparable val { get; set; }
        public int pos { get; set; }

        public int CompareTo(object obj)
        {
            if (obj is SortedItem)
            {
                return this.val.CompareTo(((SortedItem)obj).val);
            }
            else
            {
                throw new InvalidCastException();
            }
        }

    }

    /// <summary>
    /// Extension Module to Allow the Linq Query to return ToAdvancedList().
    /// </summary>
    public static class Extensions
    {
        /// <summary>
        /// Extension Class for IEnumerable to allow the conversion of output to Advancedlist<TSource>
        /// </summary>
        /// <typeparam name="TSource">Type Of Business Object</typeparam>
        /// <param name="source">Collection of IEnumerable </param>
        /// <returns></returns>
        public static AdvancedList<TSource> ToAdvancedList<TSource>(this IEnumerable<TSource> source)
        {
            AdvancedList<TSource> MyList = new AdvancedList<TSource>();
            try
            {
                foreach (var item in source)
                {
                    MyList.Add(item);
                }
                return MyList;
            }
            catch (Exception)
            {
                throw new Exception("Error converting AdvancedList");
            }

        }
    }
}

Open in new window


Surprisingly, this modified code is always so slow !!!

Why does it require so much time to sort the binded dataGridView with only 200 items ???

It seems (when debugging step by step) that the the sorting of the ArrayList sortedList containing the values of the sorting column is very fast:
sortedList.Sort();

Open in new window

But the final for loop ordering the AdvancedList items (bind to the dataGridView) appears to require a lot of time:
for (int i = 0; i < this.Count; i++)
{
       int position = ((SortedItem)sortedList[i]).pos;
       T item = (T)unsortedItems[position];
       this[i] = item;  // This instruction costs 60ms !!! Why ???
}

Open in new window

This for loop requires 12 seconds to execute (with 200 items in the AdvancedList) !

Can you give me an explanation of this extremely (and not acceptable) slow behavior ?

How could we make it much faster ?

Here is my LiNQ query and the binding code to the dataGridView:
var query = from w in context.Weighings
            where w.Processed == true
            orderby w.OF
            select new { w.Id, w.DTEnd, w.OF, w.Product, w.SetWeight, w.NetWeight, w.Status, w.UserName };
var results = query.ToAdvancedList();
dataGridView.DataSource = results;

Open in new window

0
Comment
Question by:BugRaptor
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
2 Comments
 

Accepted Solution

by:
BugRaptor earned 0 total points
ID: 39225451
I partly understood the reason of the slow automatic sorting:

Had to set the RaiseListChangedEvents property of my AdvancedList to false to prevent each item change in the internal for loop to raise an event during sorting !

var query = from w in context.Weighings
            where w.Processed == true
            orderby w.OF
            select new { w.Id, w.DTEnd, w.OF, w.Product, w.SetWeight, w.NetWeight, w.Status, w.UserName };
var results = query.ToAdvancedList();
dataGridView.DataSource = results;
results.RaiseListChangedEvents = false; // Do not raise ListChanged events on each change to the list.
                                       // (IMPORTANT in order to make the automatic sorting faster)

Open in new window

It's now faster, but not as fast as I would expect... :-(
0
 

Author Closing Comment

by:BugRaptor
ID: 39225454
Any other idea to make the automatic sorting of the dataGridView faster would be welcome !
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question