Parallel.ForEach() против цикла Foreach()
Цикл Foreach
Цикл Foreach в C# выполняется в одном потоке, и обработка выполняется последовательно один за другим. Цикл Foreach — это базовая функция C#, доступная в C# 1.0. Его выполнение в большинстве случаев медленнее, чем Parallel.Foreach .
Цикл Parallel.ForEach
Цикл Parallel.ForEach в C# выполняется в нескольких потоках, и обработка выполняется параллельно. Цикл Parallel.ForEach не является базовой функцией C# и доступен в C# 4.0 и более поздних версиях. До C# 4.0 мы не можем его использовать. В большинстве случаев его выполнение выполняется быстрее, чем foreach. Чтобы использовать цикл Parallel.ForEach, нам нужно импортировать пространство имен System.Threading.Tasks в директиву using.
Но вы хорошо знаете свое приложение и можете решить, какое из них вы хотите использовать.
Я привожу 2 примера, в первом примере традиционный цикл foreach быстрее, чем цикл Parallel.foreach, а во втором примере традиционный цикл foreach очень медленный по сравнению с Parallel.foreach.
Пример 1. Цикл Parallel.ForEach медленнее традиционного цикла Foreach.
- Список< строка >фрукты = новый список< строка >();
- фрукты.Добавить( "Яблоко" );
- фрукты.Добавить( "Банан" );
- фрукты.Добавить( "Черника" );
- фрукты.Добавить( "Ежевика" );
- фрукты.Добавить( "Черная смородина" );
- фрукты.Добавить( "Черника" );
- фрукты.Добавить( "Вишня" );
- фрукты.Добавить( "Кокос" );
- фрукты.Добавить( "Клюква" );
- фрукты.Добавить( "Дата" );
- фрукты.Добавить( "Инжир" );
- фрукты.Добавить( "Виноград" );
- фрукты.Добавить( "Гуава" );
- фрукты.Добавить( "Джек-фрут" );
- Fruits.Add( "Киви" );
- фрукты.Добавить( "Лимон" );
- фрукты.Добавить( "Лайм" );
- фрукты.Добавить( "Личи" );
- фрукты.Добавить( "Манго" );
- фрукты.Добавить( "Дыня" );
- фрукты.Добавить( "Оливковое" );
- фрукты.Добавить( "Апельсин" );
- фрукты.Добавить( "Папайя" );
- фрукты.Добавить( "Слива" );
- фрукты.Добавить( "Ананас" );
- фрукты.Добавить( "Гранат" );
- Console.WriteLine( "Печать списка с использованием цикла foreach\n" );
- var stopWatch = Секундомер.StartNew();
- foreach ( струнные фрукты во фруктах)
- {
- Console.WriteLine( "Имя плода: {0}, идентификатор потока = {1}" , плод, Thread.CurrentThread.ManagedThreadId);
- }
- Console.WriteLine( "время выполнения цикла foreach = {0} секунд\n" , stopWatch.Elapsed.TotalSeconds);
- Console.WriteLine( "Печать списка с помощью Parallel.ForEach" );
- секундомер = Секундомер.НачатьНовый();
- Parallel.ForEach(фрукты, фрукты =>
- {
- Console.WriteLine( "Имя плода: {0}, идентификатор потока = {1}" , плод, Thread.CurrentThread.ManagedThreadId);
- }
- );
- Console.WriteLine( "Время выполнения Parallel.ForEach() = {0} секунд" , stopWatch.Elapsed.TotalSeconds);
- Консоль.Прочитать();
Выход
Пример 2. Цикл Parallel.ForEach быстрее традиционного цикла Foreach.
Традиционный Foreach
- var stopWatch = Секундомер.StartNew();
- PointF firstLocation = new PointF(10f, 10f);
- PointF secondLocation = новая точкаF(10f, 50f);
- foreach ( строковый файл в Directory.GetFiles(@ "D:\Images" ))
- {
- Растровое изображение = (Растровое изображение) Image.FromFile(файл);
- используя (Graphics Graphics = Graphics.FromImage (растровое изображение))
- {
- используя (Шрифт arialFont = новый шрифт ( "Arial" , 10))
- {
- Graphics.DrawString( "Банкетешвар" , 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 = {0} секунд\n" , stopWatch.Elapsed.TotalSeconds);
Выход
Parallel.foreach
- var stopWatch = Секундомер.StartNew();
- PointF firstLocation = new PointF(10f, 10f);
- PointF secondLocation = новая точкаF(10f, 50f);
- Parallel.ForEach(Directory.GetFiles(@ "D:\Images" ), файл =>
- {
- Растровое изображение = (Растровое изображение) Image.FromFile(файл);
- используя (Graphics Graphics = Graphics.FromImage (растровое изображение))
- {
- используя (Шрифт arialFont = новый шрифт ( "Arial" , 10))
- {
- Graphics.DrawString( "Банкетешвар" , 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() = {0} секунд" , stopWatch.Elapsed.TotalSeconds);
- Консоль.Прочитать();
Выход
Чтобы проверить производительность приведенного выше кода, я использовал около 150 изображений в обоих случаях.
Вы можете видеть, что если вы выполняете какую-либо массовую задачу внутри цикла foreach, то parallel.foreach выполняется очень быстро, поэтому вы можете использовать parallel.foreach. Но если вы просто повторяете и выполняете очень небольшую задачу внутри цикла, тогда используйте традиционный цикл for .
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.