MediSoft
MediSoft

Reputation: 161

Fast way to loop over datagridview rows

I have a datagridview that contains a column with prices and more than 1000 rows i'd like apply a reduction to all those price example "-20%"

 product    price  
 product1    200
 product2    300
 product3    400

public class product
{
    public int ID {get;set;}
    public double Price {get;set;}
    public string Name {get;set;}
}
public List<product> GetListProduct()
{
       B_Entities dbCtx = new B_Entities();

        return dbCtx.B_PRODUCTS.Select(p => new Product{ ID= p.ID, Name= p.Name, Price= p.Price }).ToList();


}

dgvListeProd.DataSource = GetListProduct(); 

 Parallel.For(0, dgvListeProd.Rows.Count, index=>
            {
                  object priceValue = dgvListeProd.Rows[index].Cells[2].Value;

                if (priceValue != null)
                {
                    decimal price = Convert.ToDecimal(priceValue);
                    decimal countedPrice = (price * pourcentage) / 100;
                     countedPrice = price - countedPrice;

                    dgvListeProd.Rows[index].Cells[2].Value =(double) countedPrice;

                }
            });

This generate an aggregate exception. How to perform this task in fast way

Upvotes: 0

Views: 1999

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205619

One thing to remember once forever (or at least for Windows Forms:-)) - UI is single threaded, you cannot "optimize" it using multi threading techniques, including parallel extensions.

The fastest way to perform update task is to update the data, and let the UI show what you did. Luckily you have a data source, so apply the operation on the data source (here you can use simple for or Parallel.For), and then just call DataGridView.Refresh.

Here is a full working sample similar to your case, which processes 1M rows w/o any problem:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        static void ReducePrice(DataGridView productView, decimal percentage)
        {
            var factor = 1 - percentage / 100;
            var data = (List<Product>)productView.DataSource;
            Parallel.For(0, data.Count, index =>
            {
                var product = data[index];
                product.Price = (double)((decimal)product.Price * factor);
            });
            productView.Refresh();
        }
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var dg = new DataGridView { Dock = DockStyle.Fill, Parent = form };
            dg.DataSource = GetProductList();
            var button = new Button { Dock = DockStyle.Bottom, Parent = form, Text = "Reduce Price by 20%" };
            button.Click += (sender, e) => ReducePrice(dg, 20);
            Application.Run(form);
        }
        static List<Product> GetProductList()
        {
            var random = new Random();
            return Enumerable.Range(1, 1000000).Select(n => new Product { ID = n, Name = "Product#" + n, Price = random.Next(10, 1000) }).ToList();
        }
    }
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
    }
}

Upvotes: 2

Related Questions