Task Parallel Library (TPL) – představení


Kdo někdy tvořil v C# (a myslím, že nejen tam) vícevláknovou aplikaci, určitě uzná, že se jedná o docela zdlouhavý proces, který je navíc velmi náchylný k chybám. Ovšem od vydání .NET Frameworku 4.0 může být všechno jinak. Součástí .NET Frameworku 4.0 je totiž množina tříd z namespacu System.Threading.Tasks a část tříd z namespacu System.Threading, která se souhrnně nazývá Task Parallel Library – TPL.

TPL nabízí jednoduchý způsob, jak v aplikaci umožnit paralelní zpracování – tedy co nejefektivnější zpracování s využitím všech dostupných jader procesoru. TPL automaticky provádí například řízení vláken v ThreadPoolu a také další nízkoúrovňové detaily. V současné době je TPL doporučenou cestou, jak psát vícevláknový a paralelní kód, ovšem stále se doporučuje rozumět i přímé práci s vlákny, zámky atd.

Třída Parallel

Třída System.Threading.Tasks.Parallel je hlavní třídou celého TPL. Tato třída obsahuje několik metod, které umožňují iterovat skrze kolekce dat (konkrétně se jedná o objekty implementující rohraní IEnumerable<T>) – jedná se o statické metody Parallel.For() a Parallel.ForEach(), které definují několik přetížených verzí – viz dokumentace na MSDN. Tyto metody umožňují zadat část kódu, která má být zpracována paralelně, jinak je fungování prakticky stejné, jako u běžně zapsaných cyklů – výhoda je v tom, že třída Parallel automaticky používá vlákna z ThreadPoolu a automaticky také řídí konkurenční přístup. Důležité je poznamenat, že tento cyklus sice probíhá paralelně, ale stále blokuje hlavní vlákno.

Nejlepší je vždy ukázka:

//FOR:

//Klasický cyklus for
for (int i = 0; i < count; i++)
{
    DoWork();
}

//Paralelní cyklus for
Parallel.For(0, count, i => DoWork());

//FOREACH:

//Klasický cyklus foreach
foreach (var item in itemsCollection)
{
    DoWorkWithItem(item);
}

//Paralelní cyklus foreach
Parallel.ForEach(itemsCollection, item => DoWorkWithItem(item));

Třída Task

Další klíčovou třídou je třída System.Threading.Tasks.Task, jejíž název vypovídá o tom, že do Task Parallel Library prostě patří. V TPL se pracuje s tasky (úlohami), které jsou zpracovávány paralelně. Task reprezentuje asynchronní operaci a v některých ohledech připomíná nově vytvořené vlákno. Rozdíl je ovšem v tom, že Task poskytuje vyšší úroveň abstrakce a také některé podstatné výhody. Jak už je asi z předchozího popisu zřejmé, spuštění úlohy neblokuje hlavní vlákno.

Úlohy se dají spouštět dvěma způsoby:

  • pomocí třídy Parallel (tady vidíme, že Parallel je opravdu hlavní třída TPL)
  • přímo pomocí třídy Task – dvěma možnostmi

Opět ukázka spouštění úloh:

//TASK:

//Spouštění úlohy pomocí třídy Parallel
Parallel.Invoke(() => DoWork());

//Spouštění úlohy pomocí třídy Task
//A) Vytvoření objektu Task a spuštění úlohy
var task = new Task(() => DoWork());
task.Start();

//B) Použití TaskFactory
var task2 = Task.Factory.StartNew(() => DoWork());

Závěr

V tomto článku jsem chtěl pouze stručně představit, co je TPL a k čemu by se dalo využít. Jedná se o rozsáhlé téma, takže doufám, že se k němu ještě vrátím a podívám se na TPL blíže. Rozhodně ale mohu pro studium doporučit odkazy zmiňované dále.

Odkazy:

, , , , , , ,

Komentáře jsou uzavřeny.