Solved

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

Posted on 2013-06-06
2
744 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
  • 2
2 Comments
 

Accepted Solution

by:
BugRaptor earned 0 total points
Comment Utility
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
Comment Utility
Any other idea to make the automatic sorting of the dataGridView faster would be welcome !
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video discusses moving either the default database or any database to a new volume.

772 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now