Parallel.ForEach with DataTable and DataRows

33 views Asked by At

I read multiple times that Parallel.Foreach with lock degrades the performance. But with my below example, I can see significant improvement in DataTable operation even using Parallel.Foreach. Now I have question. As Parallel.Foreach runs on multiple core and each core has his own thread set then how CPU manages Parallel.Foreach execution and does lock only locks for the thread on that core and let other core execute their threads during that time?

`private static object _dataLock = new object();
private static void ParallelForEachTest()
{
    var limit = 50000;
    var numbers = Enumerable.Range(1, limit).ToList();
    var dataTable = new DataTable("MyTable");
    var col1 = new DataColumn("SrNo", typeof(int));
    var col2 = new DataColumn("Name", typeof(String));
    var col3 = new DataColumn("Age", typeof(decimal));
    var col4 = new DataColumn("Salary", typeof(decimal));
    dataTable.Columns.AddRange(new DataColumn[] { col1, col2, col3, col4 });

    var watch = new System.Diagnostics.Stopwatch();
    watch.Start();
    Parallel.ForEach(
        numbers,
        number =>
        {
            var dataRow = dataTable.NewRow();
            lock (_dataLock)
            {
                dataRow["SrNo"] = number.ToString();
                dataRow["Name"] = "Name_" + number.ToString();
                dataRow["Age"] = number;
                dataRow["Salary"] = number * 100.5;
                dataTable.Rows.Add(dataRow);
                dataTable.AcceptChanges();
            }
        });
    watch.Stop();
    Console.WriteLine($"Time to insert records with parallel and lock: {watch.ElapsedMilliseconds}");

    watch.Start();
    for (int number = (numbers.Count + 1); number <= numbers.Count; number++)
    {
        var dataRow = dataTable.NewRow();
        dataRow["SrNo"] = number.ToString();
        dataRow["Name"] = "Name_" + number.ToString();
        dataRow["Age"] = number;
        dataRow["Salary"] = number * 100.5;
        dataTable.Rows.Add(dataRow);
        dataTable.AcceptChanges();
    }
    watch.Stop();
    Console.WriteLine($"Time to insert records with normal loop: {watch.ElapsedMilliseconds}");

    //Parallel.ForEach(
    //    dataTable.Rows.Cast<DataRow>(),
    //    dataRow =>
    //    {
    //        Console.WriteLine($"SrNo: {dataRow["SrNo"]}, Name: {dataRow["Name"]}, Age: {dataRow["Age"]}, Salary: {dataRow["Salary"]}");                        
    //    });

    watch.Start();
    Parallel.ForEach(
        dataTable.Rows.Cast<DataRow>(),
        dataRow =>
        {                    
            lock (_dataLock)
            {
                var name = dataRow["Name"].ToString();
                //Console.WriteLine(
                //    $"Amending for -> SrNo: {dataRow["SrNo"]}, Name: {dataRow["Name"]}, Age: {dataRow["Age"]}, Salary: {dataRow["Salary"]}");
                dataRow["Name"] = name + "_Amended";
                dataTable.AcceptChanges();
            }
            
        });
    watch.Stop();
    Console.WriteLine($"Time to amend records with parallel and lock: {watch.ElapsedMilliseconds}");

    watch.Start();
    foreach (DataRow dataRow in dataTable.Rows)
    {
        var name = dataRow["Name"].ToString();
        //Console.WriteLine(
        //    $"Amending for -> SrNo: {dataRow["SrNo"]}, Name: {dataRow["Name"]}, Age: {dataRow["Age"]}, Salary: {dataRow["Salary"]}");
        dataRow["Name"] = name + "_Amended";
        dataTable.AcceptChanges();
    }
    watch.Stop();
    Console.WriteLine($"Time to amend records with normal loop: {watch.ElapsedMilliseconds}");

    //Parallel.ForEach(
    //    dataTable.Rows.Cast<DataRow>(),
    //    dataRow =>
    //    {
    //        Console.WriteLine(
    //            $"SrNo: {dataRow["SrNo"]}, Name: {dataRow["Name"]}, Age: {dataRow["Age"]}, Salary: {dataRow["Salary"]}");
    //    });
}`
0

There are 0 answers