# 如何：撰寫簡單的 Parallel.ForEach 迴圈

## 範例

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ParallelExample
{
class Program
{
static void Main()
{
// 2 million
var limit = 2_000_000;
var numbers = Enumerable.Range(0, limit).ToList();

var watch = Stopwatch.StartNew();
watch.Stop();

var watchForParallel = Stopwatch.StartNew();
watchForParallel.Stop();

Console.WriteLine($"Classical foreach loop | Total prime numbers : {primeNumbersFromForeach.Count} | Time Taken : {watch.ElapsedMilliseconds} ms."); Console.WriteLine($"Parallel.ForEach loop  | Total prime numbers : {primeNumbersFromParallelForeach.Count} | Time Taken : {watchForParallel.ElapsedMilliseconds} ms.");

Console.WriteLine("Press any key to exit.");
}

/// <summary>
/// GetPrimeList returns Prime numbers by using sequential ForEach
/// </summary>
/// <param name="inputs"></param>
/// <returns></returns>
private static IList<int> GetPrimeList(IList<int> numbers) => numbers.Where(IsPrime).ToList();

/// <summary>
/// GetPrimeListWithParallel returns Prime numbers by using Parallel.ForEach
/// </summary>
/// <param name="numbers"></param>
/// <returns></returns>
private static IList<int> GetPrimeListWithParallel(IList<int> numbers)
{

Parallel.ForEach(numbers, number =>
{
if (IsPrime(number))
{
}
});

}

/// <summary>
/// IsPrime returns true if number is Prime, else false.(https://en.wikipedia.org/wiki/Prime_number)
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
private static bool IsPrime(int number)
{
if (number < 2)
{
return false;
}

for (var divisor = 2; divisor <= Math.Sqrt(number); divisor++)
{
if (number % divisor == 0)
{
return false;
}
}
return true;
}
}
}

Imports System.Collections.Concurrent

Namespace ParallelExample
Class Program
Shared Sub Main()
' 2 million
Dim limit = 2_000_000
Dim numbers = Enumerable.Range(0, limit).ToList()

Dim watch = Stopwatch.StartNew()
watch.Stop()

Dim watchForParallel = Stopwatch.StartNew()
watchForParallel.Stop()

Console.WriteLine($"Classical foreach loop | Total prime numbers : {primeNumbersFromForeach.Count} | Time Taken : {watch.ElapsedMilliseconds} ms.") Console.WriteLine($"Parallel.ForEach loop  | Total prime numbers : {primeNumbersFromParallelForeach.Count} | Time Taken : {watchForParallel.ElapsedMilliseconds} ms.")

Console.WriteLine("Press any key to exit.")
End Sub

' GetPrimeList returns Prime numbers by using sequential ForEach
Private Shared Function GetPrimeList(numbers As IList(Of Integer)) As IList(Of Integer)
End Function

' GetPrimeListWithParallel returns Prime numbers by using Parallel.ForEach
Private Shared Function GetPrimeListWithParallel(numbers As IList(Of Integer)) As IList(Of Integer)
Dim primeNumbers = New ConcurrentBag(Of Integer)()
Parallel.ForEach(numbers, Sub(number)

If IsPrime(number) Then
End If
End Sub)
End Function

' IsPrime returns true if number is Prime, else false.(https://en.wikipedia.org/wiki/Prime_number)
Private Shared Function IsPrime(number As Integer) As Boolean
If number < 2 Then
Return False
End If

For divisor = 2 To Math.Sqrt(number)

If number Mod divisor = 0 Then
Return False
End If
Next

Return True
End Function
End Class
End Namespace


Parallel.ForEach 迴圈的運作方式類似 Parallel.For 迴圈。 迴圈會根據系統環境分割來源集合，及對多個執行緒上的作業進行排程。 系統上的處理器愈多，平行方法的執行速度愈快。 對於某些來源集合，循序迴圈的執行速度可能更快，這取決於來源的大小和迴圈執行的作業種類。 如需效能的詳細資訊，請參閱資料和工作平行處理原則中可能出現的錯誤

Parallel.ForEach(nonGenericCollection.Cast<object>(),
currentElement =>
{
});

Parallel.ForEach(nonGenericCollection.Cast(Of Object), _
Sub(currentElement)
' ... work with currentElement
End Sub)