|
|
|
|
|
foreach 循環(huán)
C# 中的foreach
循環(huán)在單個(gè)線程上運(yùn)行,并且處理一個(gè)接一個(gè)地按順序進(jìn)行。foreach
循環(huán)是 C# 的一項(xiàng)基本功能,從 C# 1.0 開(kāi)始提供。在大多數(shù)情況下,它的執(zhí)行速度比 Parallel.Foreach
慢。
Parallel.ForEach 循環(huán)
C# 中的 Parallel.ForEach
循環(huán)在多個(gè)線程上運(yùn)行,處理以并行方式進(jìn)行。Parallel.ForEach
循環(huán)不是 C# 的基本功能,它在 C# 4.0 及更高版本中可用。在 C# 4.0 之前我們不能使用它。在大多數(shù)情況下,它的執(zhí)行速度比 foreach
快。要使用 Parallel.ForEach
循環(huán),我們需要在 using
指令中導(dǎo)入System.Threading.Tasks
命名空間。
但是你非常了解你的應(yīng)用程序,并且可以決定要使用哪一個(gè)。
我給出了 2 個(gè)示例,在第一個(gè)示例中,傳統(tǒng)的 foreach
循環(huán)比 Parallel.ForEach
循環(huán)更快,而在第二個(gè)示例中,傳統(tǒng)的 foreach
循環(huán)與 Parallel.ForEach
相比非常慢。
示例 1: Parallel.ForEach 循環(huán)比傳統(tǒng)的 foreach 循環(huán)慢。
List<string> fruits = new List<string>();
fruits.Add("Apple");
fruits.Add("Banana");
fruits.Add("Bilberry");
fruits.Add("Blackberry");
fruits.Add("Blackcurrant");
fruits.Add("Blueberry");
fruits.Add("Cherry");
fruits.Add("Coconut");
fruits.Add("Cranberry");
fruits.Add("Date");
fruits.Add("Fig");
fruits.Add("Grape");
fruits.Add("Guava");
fruits.Add("Jack-fruit");
fruits.Add("Kiwi fruit");
fruits.Add("Lemon");
fruits.Add("Lime");
fruits.Add("Lychee");
fruits.Add("Mango");
fruits.Add("Melon");
fruits.Add("Olive");
fruits.Add("Orange");
fruits.Add("Papaya");
fruits.Add("Plum");
fruits.Add("Pineapple");
fruits.Add("Pomegranate");
Console.WriteLine("Printing list using foreach loop\n");
var stopWatch = Stopwatch.StartNew();
foreach (string fruit in fruits)
{
Console.WriteLine("Fruit Name: {0}, Thread Id= {1}", fruit, Thread.CurrentThread.ManagedThreadId);
}
Console.WriteLine("foreach loop execution time = {0} seconds\n", stopWatch.Elapsed.TotalSeconds);
Console.WriteLine("Printing list using Parallel.ForEach");
stopWatch = Stopwatch.StartNew();
Parallel.ForEach(fruits, fruit =>
{
Console.WriteLine("Fruit Name: {0}, Thread Id= {1}", fruit, Thread.CurrentThread.ManagedThreadId);
}
);
Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", stopWatch.Elapsed.TotalSeconds);
Console.Read();
輸出
示例 2:Parallel.ForEach 循環(huán)比傳統(tǒng)的 foreach 循環(huán)更快。
var stopWatch = Stopwatch.StartNew();
PointF firstLocation = new PointF(10 f, 10 f);
PointF secondLocation = new PointF(10 f, 50 f);
foreach(string file in Directory.GetFiles(@ "D:\Images"))
{
Bitmap bitmap = (Bitmap) Image.FromFile(file);
using(Graphics graphics = Graphics.FromImage(bitmap))
{
using(Font arialFont = new Font("Arial", 10))
{
graphics.DrawString("Banketeshvar", arialFont, Brushes.Blue, firstLocation);
graphics.DrawString("Narayan", arialFont, Brushes.Red, secondLocation);
}
}
bitmap.Save(Path.GetDirectoryName(file) + "Foreachloop" + "\\" + Path.GetFileNameWithoutExtension(file) + Guid.NewGuid()
.ToString() + ".jpg");
}
Console.WriteLine("foreach loop execution time = {0} seconds\n", stopWatch.Elapsed.TotalSeconds);
輸出
var stopWatch = Stopwatch.StartNew();
PointF firstLocation = new PointF(10 f, 10 f);
PointF secondLocation = new PointF(10 f, 50 f);
Parallel.ForEach(Directory.GetFiles(@ "D:\Images"), file =>
{
Bitmap bitmap = (Bitmap) Image.FromFile(file);
using(Graphics graphics = Graphics.FromImage(bitmap))
{
using(Font arialFont = new Font("Arial", 10))
{
graphics.DrawString("Banketeshvar", arialFont, Brushes.Blue, firstLocation);
graphics.DrawString("Narayan", arialFont, Brushes.Red, secondLocation);
}
}
bitmap.Save(Path.GetDirectoryName(file) + "Parallel" + "\\" + Path.GetFileNameWithoutExtension(file) + Guid.NewGuid()
.ToString() + ".jpg");
});
Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", stopWatch.Elapsed.TotalSeconds);
Console.Read();
輸出
結(jié)論
為了測(cè)試上述代碼的性能,我在這兩種情況下都使用了大約 150 張圖像。
你可以看到,如果你在 foreach
循環(huán)內(nèi)執(zhí)行任何批量任務(wù),那么 Parallel.ForEach
非常快,因此你可以使用 Parallel.ForEach
。
Parallel.ForEach
循環(huán)的工作方式類似于Parallel.For循
環(huán)。循環(huán)對(duì)源集合進(jìn)行分區(qū),并根據(jù)系統(tǒng)環(huán)境在多個(gè)線程上安排工作。系統(tǒng)上的處理器越多,并行方法運(yùn)行得越快。對(duì)于某些源集合,順序循環(huán)可能更快,具體取決于源的大小和循環(huán)執(zhí)行的工作類型。
如果你只是在循環(huán)內(nèi)迭代并執(zhí)行非常小的任務(wù),那么請(qǐng)使用傳統(tǒng)的for
循環(huán)。
相關(guān)文章