How to do it...

  1. Start off by creating two methods in the Demo class. Call one method ReadCollectionForEach() and pass it a parameter of List<string>. Create a second method called ReadCollectionParallelForEach() that also accepts a parameter of List<string>:
        public class Demo 
{
public double ReadCollectionForEach(List<string> intCollection)
{

}

public double ReadCollectionParallelForEach(List<string>
intCollection)
{

}
}
  1. In the ReadCollectionForEach() method, add a standard foreach loop that will iterate over the collection of strings passed to it and write the value it finds to the console window. Then, clear the console window. Use a timer to keep track of the total seconds elapsed during the foreach loop:
        var timer = Stopwatch.StartNew(); 
foreach (string integer in intCollection)
{
WriteLine(integer);
Clear();
}
return timer.Elapsed.TotalSeconds;
  1. In the second method, called ReadCollectionParallelForEach(), do the same. However, instead of using a standard foreach loop, add a Parallel.ForEach loop. You will notice that the Parallel.ForEach loop looks slightly different. The signature of Parallel.ForEach requires that you pass it an enumerable data source (List<string> intCollection) and define an action, which is the delegate that is invoked for every iteration (integer):
        var timer = Stopwatch.StartNew(); 
Parallel.ForEach(intCollection, integer =>
{
WriteLine(integer);
Clear();
});
return timer.Elapsed.TotalSeconds;
  1. When you have added all the required code, your Demo class should look like this:
        public class Demo 
{
public double ReadCollectionForEach(List<string> intCollection)
{
var timer = Stopwatch.StartNew();
foreach (string integer in intCollection)
{
WriteLine(integer);
Clear();
}
return timer.Elapsed.TotalSeconds;
}

public double ReadCollectionParallelForEach(List<string>
intCollection)
{
var timer = Stopwatch.StartNew();
Parallel.ForEach(intCollection, integer =>
{
WriteLine(integer);
Clear();
});
return timer.Elapsed.TotalSeconds;
}
}
  1. In the console application, create the List<string> collection and pass it to the two methods created in the Demo class. You will notice that we are only creating a collection of 500 items. After the code is completed, return the time elapsed in seconds and output it to the console window:
        List<string> integerList = new List<string>(); 
for (int i = 0; i <= 500; i++)
{
integerList.Add(i.ToString());
}
Demo oRecipe = new Demo();
double timeElapsed1 = oRecipe.ReadCollectionForEach(integerList);
double timeElapsed2 = oRecipe.ReadCollectionParallelForEach(
integerList);
WriteLine($"foreach executed in {timeElapsed1}");
WriteLine($"Parallel.ForEach executed in {timeElapsed2}");
  1. Run your application. From the output displayed, you will see the difference in performance. The Parallel.ForEach loop actually took longer to complete than the foreach loop:
  1. Let's use a different example now. We will create a process-intensive task and measure the performance gain that the Parallel.ForEach loop will give us. Create two methods called CreateWriteFilesForEach() and CreateWriteFilesParallelForEach() that both take the List<string> collection as the parameter:
        public class Demo 
{
public void CreateWriteFilesForEach(List<string> intCollection)
{

}

public void CreateWriteFilesParallelForEach(List<string>
intCollection)
{

}
}
  1. Add the following code to the CreateWriteFilesForEach() method. This code starts the timer and executes the standard foreach loop on the List<string> object. It then writes the elapsed time out to the console window:
        WriteLine($"Start foreach File method"); 
var timer = Stopwatch.StartNew();
foreach (string integer in intCollection)
{

}
WriteLine($"foreach File method executed in {timer.Elapsed.TotalSeconds} seconds");
  1. Inside the foreach loop, add the code to check whether a file exists with the specific name created by appending the integer value to the filename portion of the filePath variable. Create the file (ensuring that you use the Dispose method so as not to lock the file when trying to write to it) and write some text to the newly created file:
        string filePath =  $"C:	empoutputForEach_Log{integer}.txt"; 
if (!File.Exists(filePath))
{
File.Create(filePath).Dispose();
using (StreamWriter sw = new StreamWriter(filePath, false))
{
sw.WriteLine($"{integer}. Log file start: {DateTime.Now.ToUniversalTime().ToString()}");
}
}
  1. Next, add this code to the CreateWriteFilesParallelForEach() method, which basically performs the same function as the CreateWriteFilesForEach() method, but uses a Parallel.ForEach loop to create and write files:
        WriteLine($"Start Parallel.ForEach File method"); 
var timer = Stopwatch.StartNew();
Parallel.ForEach(intCollection, integer =>
{

});
WriteLine($"Parallel.ForEach File method executed in {timer.Elapsed.TotalSeconds} seconds");
  1. Add the slightly modified file-creation code inside the Parallel.ForEach loop:
        string filePath = $"C:	empoutputParallelForEach_Log{
integer}.txt";
if (!File.Exists(filePath))
{
File.Create(filePath).Dispose();
using (StreamWriter sw = new StreamWriter(filePath, false))
{
sw.WriteLine($"{integer}. Log file start: {DateTime.Now.ToUniversalTime().ToString()}");
}
}
  1. When you are done, your code needs to look like this:
        public class Demo 
{
public void CreateWriteFilesForEach(List<string> intCollection)
{
WriteLine($"Start foreach File method");
var timer = Stopwatch.StartNew();
foreach (string integer in intCollection)
{
string filePath = $"C: empoutputForEach_Log{integer}.txt";
if (!File.Exists(filePath))
{
File.Create(filePath).Dispose();
using (StreamWriter sw = new StreamWriter(filePath, false))
{
sw.WriteLine($"{integer}. Log file start: {DateTime.Now.ToUniversalTime().ToString()}");
}
}
}
WriteLine($"foreach File method executed in {
timer.Elapsed.TotalSeconds} seconds");
}

public void CreateWriteFilesParallelForEach(List<string>
intCollection)
{
WriteLine($"Start Parallel.ForEach File method");
var timer = Stopwatch.StartNew();
Parallel.ForEach(intCollection, integer =>
{
string filePath = $"C: empoutputParallelForEach_Log
{integer}.txt";
if (!File.Exists(filePath))
{
File.Create(filePath).Dispose();
using (StreamWriter sw = new StreamWriter(filePath, false))
{
sw.WriteLine($"{integer}. Log file start: {DateTime.Now.ToUniversalTime().ToString()}");
}
}
});
WriteLine($"Parallel.ForEach File method executed in {timer.Elapsed.TotalSeconds} seconds");
}
}
  1. Head over to the console application, modify the List<string> object slightly, and increase the count from 500 to 1000. Then, call the file methods created in the Demo class:
        List<string> integerList = new List<string>(); 
for (int i = 0; i <= 1000; i++)
{
integerList.Add(i.ToString());
}

Demo oRecipe = new Demo();
oRecipe.CreateWriteFilesForEach(integerList);
oRecipe.CreateWriteFilesParallelForEach(integerList);
ReadLine();
  1. Finally, when you are ready, make sure that you have the C:tempoutput directory and that there aren't any other files in that directory. Run your application and review the output in the console window. This time round, we can see that the Parallel.ForEach loop has made a huge difference. The performance gain is massive and heralds a 47.42 percent performance increase over the standard foreach loop:
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.37.126