Wracamy do kursu o TPL. Dziś trochę informacji faktów o .For oraz .ForEach.
Te dwie metody dają podstawowy sposób na zrównoleglenie naszego kodu bez większego wysiłku
Parallel.For(lowerBound, exclusiveUpperBound, () => { /*action*/});
Parallel.ForEach<int>(Enumerable.Range(1, 100), (int item) => { /*body*/});
Tak więc prościej już by się nie dało :). Jednak funkcje te mają możliwość przyjmowania dodatkowych parametrów.
ParallelOptions
Za pomocą tego parametru możemy ustawić kilka dodatkowych właściwości takich jak:
- maksymalny stopień paralelizacji (MaxDegreeOfParallelism)
- token anulacji (CancellationToken)
- własny scheduler zadań (TaskScheduler)
Zakończenie pętli
Sytuacja, gdy pętla zakończy się powodzeniem jest jak najbardziej przez nas pożądana, ale oczywiście trzeba przygotować się na sytuację, gdy coś się nie uda lub pętla zakończy się przedwcześnie. Aby sprawdzić, jak zakończyła się pętla należy sprawdzić zawartość zmiennej zwracanej przez Parallel.For – zwracany jest obiekt ParallelLoopResult.
Stop
Parallel.For(1, 1000, (int i, ParallelLoopState state) =>
{
/*action*/
if (found)
{
state.Stop();
}
});
Warto zauważyć inną definicję ciała pętli. Jeśli chcemy skorzystać z możliwości zakończenia pętli przedwcześnie musimy wykorzystać definicję przyjmującą jako argumenty indeks oraz typ ParallelLoopState. Po wywołaniu metody Stop, kolejne iteracje nie będą uruchamiane. Jeśli chcemy przerwać już uruchomione iteracje możemy sprawdzić właściwość IsStopped i odpowiednio na nią reagować.
Break
Break działa podobnie do Stop ale daje dodatkowe gwarancje. Jeśli Break zostanie wywołane z 50 iteracji, spowoduje zatrzymanie wywoływania iteracji powyżej 50-tej, ale iteracje 0-49 nadal będą wywołane. Break może zostać wywołane wielokrotnie a najniższa iteracja, z której została wywołana metoda zostaje zapisana we właściwości: LowestBreakIteration.
Stop i Break nie mogą być używane równocześnie.
Wyjątki
Czasem mamy sytuację, iż nasze ciało pętli rzuca wyjątkiem. Jak sobie radzić w takiej sytuacji. TPL wprowadza nowy typ wyjątku: AggregateException. Nie różni się to od zwykłego wyjątku, z tym, że umożliwia zapisanie wiele wyjątków w polu InnerException. Aby sprawdzić czy w jakiejś iteracji nie wystąpił wyjątek należy sprawdzić właściwość IsExceptional na obiekcie ParallelLoopState.
Na dziś to tyle. Zachęcam do zabawy TPL w .NET 4.0 naprawdę przydatna sprawa.
Founder of Octal Solutions a .NET software house.
Passionate dev, blogger, occasionally speaker, one of the leaders of Wroc.NET user group. Microsoft MVP. Podcaster – Ostrapila.pl