Funkční paralelismus (Task Parallel Library)
Knihovna Task Parallel Library (TPL), jak naznačuje její název, je založena na pojmu úloha. Termín úloh rovnoběžnosti odkazuje na jeden nebo více nezávislých úloh spuštěna souběžně. Úloha představuje asynchronní operaci a v některých ohledech je podobná vytváření nového vlákna nebo pracovní položky fondu vláken, ovšem na vyšší úrovni abstrakce. Úlohy poskytují dvě hlavní výhody:
Větší škálovatelnost a efektivnější využívání systémových prostředků.
Na pozadí jsou úlohy řazeny do fronty fondu vláken, který byl vylepšen o algoritmy (například hill-climbing), které naleznou a upravují počet vláken na takovou hodnotu, která maximalizuje propustnost. Toto dělá úlohy relativně lehké a lze jich vytvořit mnoho pro umožnění jemně odstupňovaného paralelismu. Pro doplnění jsou využity všeobecně známé work-stealing algoritmy, které poskytují vyvažování zatížení.
Více programového ovládání než je umožněno s vláknem nebo pracovní položkou.
Úlohy a architektura kolem nich vytvořená poskytují bohatou sadu rozhraní (API), které podporují čekání, zrušení, pokračování, robustní zpracování výjimek, podrobný stav, vlastní plánování a další.
Pro oba z těchto důvodů jsou v rozhraní .NET Framework 4 úlohy upřednostňovaným rozhraním API pro psaní vícevláknového, asynchronního a paralelního kódu.
Vytvoření a spuštění úloh implicitně
Metoda Parallel.Invoke umožňuje pohodlný způsob, jak souběžně spustit libovolný počet různých příkazů. Stačí pouze předat delegáta Action pro každou položku práce. Nejsnadnější způsob, jak vytvořit tyto delegáty je použití lambda výrazů. Lambda výraz může buďto volat pojmenovanou metodu, nebo poskytnout vložený kód. Následující příklad zobrazuje základní volání Invoke, které vytvoří a spustí dvě úlohy, které běží souběžně.
Poznámka |
---|
Tato dokumentace používá k definování delegátů v TPL lambda výrazy.Pokud nejste obeznámeni s lambda výrazy v jazyce C# nebo Visual Basic, pokračujte na Lambda výrazy v PLINQ a TPL. |
Parallel.Invoke(Sub() DoSomeWork(), Sub() DoSomeOtherWork())
Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Poznámka |
---|
Počet instancí Task, které jsou vytvořeny na pozadí pomocí Invoke, nemusí být nutně roven počtu zadaných delegátů.Knihovna TPL může využít různé optimalizace, zejména s velkým počtem delegátů. |
Další informace naleznete v tématu Postupy: Použití Parallel.Invoke k vykonávání paralelních operací.
Pro větší kontrolu nad spouštěním úloh nebo pro navrácení hodnoty z úlohy je nutné pracovat s objekty Task více explicitně.
Vytvoření a spuštění úloh explicitně
Úloha je reprezentována třídou System.Threading.Tasks.Task. Úloha, která navrací hodnotu je reprezentována třídou System.Threading.Tasks.Task<TResult>, která dědí z Task. Objekt úlohy zpracovává podrobnosti infrastruktury a poskytuje metody a vlastnosti, které jsou přístupné z volajícího vlákna po celou dobu trvání úlohy. Lze například kdykoli přistupovat k vlastnosti Status úlohy a zjistit, zda byla spuštěna, dokončena, zrušena, nebo byla vyvolána výjimka. Stav je reprezentován výčtem TaskStatus.
Když je vytvořena úloha, je jí zadán uživatelský delegát, který provádí zapouzdření kódu, který úloha provede. Tento delegát může být vyjádřen jako pojmenovaný delegát, anonymní metoda nebo lambda výraz. Lambda výrazy mohou obsahovat volání pojmenované metody, jak je znázorněno v následujícím příkladu.
' Create a task and supply a user delegate by using a lambda expression.
Dim taskA = New Task(Sub() Console.WriteLine("Hello from taskA."))
' Start the task.
taskA.Start()
' Output a message from the joining thread.
Console.WriteLine("Hello from the joining thread.")
' Output:
' Hello from the joining thread.
' Hello from taskA.
// Create a task and supply a user delegate by using a lambda expression.
var taskA = new Task(() => Console.WriteLine("Hello from taskA."));
// Start the task.
taskA.Start();
// Output a message from the joining thread.
Console.WriteLine("Hello from the calling thread.");
/* Output:
* Hello from the joining thread.
* Hello from taskA.
*/
Lze také použít metodu StartNew pro vytvoření a spuštění úlohy v jedné operaci. To je preferovaný způsob vytvoření a spuštění úlohy, pokud vytváření a plánování nemusí být odděleny, jak ukazuje následující příklad
' Better: Create and start the task in one operation.
Dim taskA = Task.Factory.StartNew(Sub() Console.WriteLine("Hello from taskA."))
' Output a message from the joining thread.
Console.WriteLine("Hello from the joining thread.")
// Create and start the task in one operation.
var taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));
// Output a message from the joining thread.
Console.WriteLine("Hello from the joining thread.");
Úkol zpřístupňuje statickou vlastnost Factory, který vrací výchozí instance TaskFactory, takže může volat metodu jako Task.Factory.StartNew(…). Také v tomto příkladu, jelikož úlohy jsou typu System.Threading.Tasks.Task<TResult>, každá má veřejnou vlastnost Result, která obsahuje výsledek výpočtu. Úlohy běží asynchronně a mohou být dokončeny v libovolném pořadí. Pokud Result je před dokončením výpočtu přistupovat, vlastnost bude blokovat vlákno dokud hodnota je k dispozici.
Dim taskArray() = {Task(Of Double).Factory.StartNew(Function() DoComputation1()),
Task(Of Double).Factory.StartNew(Function() DoComputation2()),
Task(Of Double).Factory.StartNew(Function() DoComputation3())}
Dim results() As Double
ReDim results(taskArray.Length)
For i As Integer = 0 To taskArray.Length
results(i) = taskArray(i).Result
Next
Task<double>[] taskArray = new Task<double>[]
{
Task<double>.Factory.StartNew(() => DoComputation1()),
// May be written more conveniently like this:
Task.Factory.StartNew(() => DoComputation2()),
Task.Factory.StartNew(() => DoComputation3())
};
double[] results = new double[taskArray.Length];
for (int i = 0; i < taskArray.Length; i++)
results[i] = taskArray[i].Result;
Další informace naleznete v tématu Postupy: Jak vrátit hodnotu z úlohy.
Při použití lambda výraz delegování úkolu Vytvoření máte přístup k proměnné, které jsou zobrazeny v tomto zdrojový kód. Však v některých případech, zejména v rámci smyčky, nemá kyslíkovou zachytit proměnné podle očekávání. Zaznamená pouze konečné hodnoty, nikoli hodnotu, jako je mutates po každé iteraci. Přístup na hodnotu v každé iteraci poskytnutím objektu stavu úkolu pomocí jejího konstruktoru jak ukazuje následující příklad:
Class MyCustomData
Public CreationTime As Long
Public Name As Integer
Public ThreadNum As Integer
End Class
Sub TaskDemo2()
' Create the task object by using an Action(Of Object) to pass in custom data
' in the Task constructor. This is useful when you need to capture outer variables
' from within a loop.
' As an experiement, try modifying this code to capture i directly in the lamda,
' and compare results.
Dim taskArray() As Task
ReDim taskArray(10)
For i As Integer = 0 To taskArray.Length - 1
taskArray(i) = New Task(Sub(obj As Object)
Dim mydata = CType(obj, MyCustomData)
mydata.ThreadNum = Thread.CurrentThread.ManagedThreadId
Console.WriteLine("Hello from Task #{0} created at {1} running on thread #{2}.",
mydata.Name, mydata.CreationTime, mydata.ThreadNum)
End Sub,
New MyCustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks}
)
taskArray(i).Start()
Next
End Sub
class MyCustomData
{
public long CreationTime;
public int Name;
public int ThreadNum;
}
void TaskDemo2()
{
// Create the task object by using an Action(Of Object) to pass in custom data
// in the Task constructor. This is useful when you need to capture outer variables
// from within a loop. As an experiement, try modifying this code to
// capture i directly in the lambda, and compare results.
Task[] taskArray = new Task[10];
for(int i = 0; i < taskArray.Length; i++)
{
taskArray[i] = new Task((obj) =>
{
MyCustomData mydata = (MyCustomData) obj;
mydata.ThreadNum = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Hello from Task #{0} created at {1} running on thread #{2}.",
mydata.Name, mydata.CreationTime, mydata.ThreadNum)
},
new MyCustomData () {Name = i, CreationTime = DateTime.Now.Ticks}
);
taskArray[i].Start();
}
}
Tento stav je předán jako argument k delegování úkolu a je přístupné z objektu úlohy pomocí AsyncState vlastnost. Předávání dat pomocí konstruktoru také poskytují výhodu malého výkonu v některých scénářích.
číslo ID úkolu,
Každá úloha obdrží celočíselný identifikátor ID, který ji jednoznačně identifikuje v doméně aplikace a který je přístupný prostřednictvím vlastnosti Id. ID je užitečné při prohlížení informace o úloze v oknech Parallel Stacks a Parallel Tasks ladícího nástroje sady Visual Studio. ID využívá líné vytváření, což znamená, že není vytvořeno dokud se o něj nepožádá, proto může mít úloha při každém spuštění programu jiné ID. Další informace o zobrazení ID úkolů v debuggeru naleznete Pomocí okno paralelní balíčky.
Možnosti vytvoření úlohy
Většina rozhraní API, které vytvářejí úlohy poskytují přetížení, které přijímají TaskCreationOptions parametr. Zadáním jedné z těchto možností lze dát pokyn plánovači úloh, jak naplánovat úlohy ve fondu vláken. V následující tabulce jsou uvedeny různé možnosti pro vytvářené úlohy.
Prvek |
Popis |
---|---|
None |
Výchozí možnost, pokud není zadána jiná možnost. Plánovač používá k plánování úlohy jeho výchozí heuristické metody. |
PreferFairness |
Určuje, že úlohy by měly být naplánovány tak, že úlohy vytvořené dříve se budou pravděpodobně provádět dříve a později vytvořené úlohy se budou s větší pravděpodobností provádět později. |
LongRunning |
Určuje, že úloha představuje o dlouhotrvající operaci. |
AttachedToParent |
Určuje, že úloha by měla být vytvořena jako připojená podřízená úloha aktuální úlohy, pokud existuje. Další informace naleznete v tématu Vnořené a podřízené úlohy. |
Možnosti lze kombinovat pomocí logické bitové operace OR. Následující příklad zobrazuje úkol, který má LongRunning a PreferFairness možnost.
Dim task3 = New Task(Sub() MyLongRunningMethod(),
TaskCreationOptions.LongRunning Or TaskCreationOptions.PreferFairness)
task3.Start()
var task3 = new Task(() => MyLongRunningMethod(),
TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
task3.Start();
Vytváření pokračování úlohy
Metoda Task.ContinueWith a metoda Task<TResult>.ContinueWith umožňují zadání úlohy, která má být spuštěna při dokončení předchozí úlohy. Delegátu pokračující úlohy je předána reference na předchůdce, tak aby mohl zkontrolovat jeho stav. Kromě toho může být z předchůdce předána do pokračování uživatelsky definovaná hodnota ve vlastnosti Result, takže výstup předchůdce může sloužit jako vstup pro pokračování. V následujícím příkladu je kódem programu spuštěna úloha getData. Poté, když se getData dokončí, je automaticky spuštěna úloha analyzeData a po dokončení analyzeData je spuštěna úloha reportData. Úloha getData vytváří jako výsledek bajtové pole, které je předáno do analyzeData. Úloha analyzeData toto pole zpracuje a vrátí výsledek, jehož typ je odvozen z návratového typu metody Analyze. Úloha reportData přebírá vstup z analyzeData a vytváří výsledek, jehož typ je odvozen podobným způsobem, a který je programu k dispozici ve vlastnosti Result.
Dim getData As Task(Of Byte()) = New Task(Of Byte())(Function() GetFileData())
Dim analyzeData As Task(Of Double()) = getData.ContinueWith(Function(x) Analyze(x.Result))
Dim reportData As Task(Of String) = analyzeData.ContinueWith(Function(y As Task(Of Double)) Summarize(y.Result))
getData.Start()
System.IO.File.WriteAllText("C:\reportFolder\report.txt", reportData.Result)
Task<byte[]> getData = new Task<byte[]>(() => GetFileData());
Task<double[]> analyzeData = getData.ContinueWith(x => Analyze(x.Result));
Task<string> reportData = analyzeData.ContinueWith(y => Summarize(y.Result));
getData.Start();
//or...
Task<string> reportData2 = Task.Factory.StartNew(() => GetFileData())
.ContinueWith((x) => Analyze(x.Result))
.ContinueWith((y) => Summarize(y.Result));
System.IO.File.WriteAllText(@"C:\reportFolder\report.txt", reportData.Result);
ContinueWhenAll a ContinueWhenAny metody umožňují pokračovat z několika úkolů. Další informace naleznete v tématu Pokračující úlohy a Postupy: Zřetězení více úkolů s Continuations.
Vytváření odpojených vnořených úloh
Při vytvoří nový úkol a zadat kód uživatele pracující v úkolu AttachedToParent možnost, nový úkol nebyl synchronizován s vnější úkol v jakékoli zvláštní způsob. Tyto úkoly nazývají sejmutým vnořené úkolu. Následující příklad zobrazuje úlohu, která vytváří jednu odpojenou vnořenou úlohu.
Dim outer = Task.Factory.StartNew(Sub()
Console.WriteLine("Outer task beginning.")
Dim child = Task.Factory.StartNew(Sub()
Thread.SpinWait(5000000)
Console.WriteLine("Detached task completed.")
End Sub)
End Sub)
outer.Wait()
Console.WriteLine("Outer task completed.")
' Output:
' Outer task beginning.
' Outer task completed.
' Detached child completed.
var outer = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer task beginning.");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(5000000);
Console.WriteLine("Detached task completed.");
});
});
outer.Wait();
Console.WriteLine("Outer task completed.");
/* Output:
Outer task beginning.
Outer task completed.
Detached task completed.
*/
Všimněte si, že vnější úloha nečeká na dokončení vnořené úlohy.
Vytváření podřízených úloh
Když kód uživatele pracující v úkolu vytvoří úkol s AttachedToParent možnost Nový úkol je označován jako podřízený úkol pocházející z úkolu, který je označován jako nadřazeného úkolu. Pro získání strukturovaného paralelismu úloh lze použít AttachedToParent, protože nadřazená úloha implicitně čeká na dokončení všech podřízených úloh. Následující příklad zobrazuje úlohu, která vytváří jednu podřízenou úlohu:
Dim parent = Task.Factory.StartNew(Sub()
Console.WriteLine("Parent task beginning.")
Dim child = Task.Factory.StartNew(Sub()
Thread.SpinWait(5000000)
Console.WriteLine("Attached child completed.")
End Sub,
TaskCreationOptions.AttachedToParent)
End Sub)
outer.Wait()
Console.WriteLine("Parent task completed.")
' Output:
' Parent task beginning.
' Attached child completed.
' Parent task completed.
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Parent task beginning.");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(5000000);
Console.WriteLine("Attached child completed.");
}, TaskCreationOptions.AttachedToParent);
});
parent.Wait();
Console.WriteLine("Parent task completed.");
/* Output:
Parent task beginning.
Attached task completed.
Parent task completed.
*/
Další informace naleznete v tématu Vnořené a podřízené úlohy.
Čekání na úlohy
System.Threading.Tasks.Task Typu a System.Threading.Tasks.Task<TResult> typu poskytují několik přetížení Task.Wait a Task<TResult>.Wait Metoda umožňující čekat na dokončení úlohy. Kromě toho přetížení statické metody Task.WaitAll a metody Task.WaitAny umožňují čekat na dokončení některých nebo všech úloh v poli.
Obvykle se na úlohu čeká z některého z těchto důvodů:
Hlavní vlákno závisí na konečném výsledku vypočítaném úlohou.
Je potřeba zpracovat výjimky, které mohou být vyvolány z úlohy.
Následující příklad zobrazuje základní vzor, který nezahrnuje zpracování výjimek.
Dim tasks() =
{
Task.Factory.StartNew(Sub() MethodA()),
Task.Factory.StartNew(Sub() MethodB()),
Task.Factory.StartNew(Sub() MethodC())
}
' Block until all tasks complete.
Task.WaitAll(tasks)
' Continue on this thread...
Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};
//Block until all tasks complete.
Task.WaitAll(tasks);
// Continue on this thread...
Příklad zpracování výjimek, viz Postupy: Zpracování výjimek vyvolaných úlohou.
Některé přetížení umožňují určit časový limit a jiné přijímají jako vstupní parametr další token CancellationToken, aby mohlo být samotné čekání zrušeno buď programově, nebo jako odpověď na uživatelský vstup.
Při čekání na úlohu se implicitně čeká na všechny podřízené dané úlohy, kteří byli vytvořeni pomocí možnosti TaskCreationOptions AttachedToParent. Task.Wait vrátí hodnotu okamžitě, pokud úloha již byla dokončena. Jakékoli výjimky způsobené úlohou budou vyvolány metodou Wait, i když byla metoda Wait volána po dokončení úlohy.
Další informace naleznete v tématu Postupy: Čekání na dokončení jedné nebo více úloh.
Zpracování výjimek v úlohách
Pokud úloha vyvolá jednu nebo více výjimek, výjimky jsou obaleny do AggregateException. Tato výjimka se šíří zpět k vláknu spojeného s úlohou, které je obvykle vláknem čekajícím na úlohu nebo pokoušejícím se přistoupit k vlastnosti Result úlohy. Toto chování slouží k vynucení, aby při všech neošetřených výjimkách ve výchozím nastavení zásady rozhraní .NET Framework strhly proces. Volající kód může výjimky zpracovávat pomocí metod Wait, WaitAll nebo WaitAny nebo vlastnosti Result() úlohy či skupiny úloh a pomocí obalení metody Wait v bloku try-catch.
Spojovací vlákno může také výjimky zpracovávat přístupem k vlastnosti Exception, než je úloha uvolněna z paměti. Přístupem k této vlastnosti, nebude neošetřenou výjimkou spouštěno šíření výjimky, které strhne proces, pokud je objekt finalizován.
Další informace o výjimkách a úlohách naleznete v tématu Zpracovávání vyjímek (Task Parallel Library) a Postupy: Zpracování výjimek vyvolaných úlohou.
Zrušení úloh
Třída Task podporuje kooperativní zrušení a je plně integrována s třídu System.Threading.CancellationTokenSource a třídou System.Threading.CancellationToken, které jsou nově v rozhraní .NET Framework verze 4. Mnoho konstruktorů ve třídě System.Threading.Tasks.Task přijímají jako vstupní parametr CancellationToken. Mnoho přetížení StartNew také přijímá CancellationToken.
Použitím třídy CancellationTokenSource je možné vytvořit token a vyslat žádost zrušení později. Je potřeba předat token jako argument instanci Task a také odkazovat stejný token v uživatelském delegátovi, který provádí reakci na žádost o zrušení. Další informace naleznete v tématu Zrušení úlohy a Postupy: Zrušit úlohy a její děti.
Třída TaskFactory
Třída TaskFactory poskytuje statické metody, které provádí zapouzdření některých běžný schémat pro vytváření a spouštění úloh a pokračujících úloh.
Nejběžnější vzor StartNew vytvoří a spustí úlohu v jednom příkazu. Další informace naleznete v tématu StartNew().
Při vytváření úlohy pokračování z více transfúzí použít ContinueWhenAll Metoda neboContinueWhenAnyMetoda nebo jejich ekvivalenty v Task<TResult> Třída Další informace naleznete v tématu Pokračující úlohy.
K zapouzdření asynchronní Model programování BeginX a EndX metod Task nebo Task<TResult> instance, použijte FromAsync metod. Další informace naleznete v tématu TPL a tradiční asynchronní programování v .NET.
Výchozí TaskFactory je přístupná jako statická vlastnost ve třídě Task nebo třídě Task<TResult>. Také je možno vytvořit instanci TaskFactory přímo a určit různé možnosti, které zahrnují token CancellationToken, možnost TaskCreationOptions, možnost TaskContinuationOptions nebo TaskScheduler. Jakékoliv možnosti, které jsou zadány při vytváření továrny úloh, budou použity pro všechny úlohy, které továrna vytvoří. Pouze pokud je s úloha je vytvořena pomocí výčtu TaskCreationOptions, pak jsou továrny úloh přepsány možnostmi úlohy.
Úlohy bez delegátů
V některých případech můžete chtít použít Task k zapouzdření některé asynchronní operace, kterou provádí externí komponenta namísto uživatelského delegáta. Pokud je operace založena na vzoru Begin/End modelu asynchronního programování, můžete použít metody FromAsync. Pokud to není tento případ, můžete použít objekt TaskCompletionSource<TResult>, který obalí operaci do úlohy a tím získáte některé výhody programovatelnosti Task, například podporu šíření výjimek a pokračování. Další informace naleznete v tématu TaskCompletionSource<TResult>.
Vlastní plánovače
Většině vývojářů aplikací a knihoven nezáleží na tom, na kterém procesoru je úloha spuštěna, jak synchronizuje svou práci s ostatními úkoly nebo jak je naplánována v System.Threading.ThreadPool. Vyžadují pouze, aby byly tyto úkony v hostitelském počítači prováděny tak efektivně, jak je to možné. Pokud požadujete jemněji odstupňovanou kontrolu nad podrobnostmi plánování, Task Parallel Library umožňuje konfigurovat některá nastavení výchozího plánovače úloh a dokonce umožňuje zadat vlastní plánovač. Další informace naleznete v tématu TaskScheduler.
Související datové struktury
TPL má několik nových veřejných typů, které jsou použitelné jak v situacích paralelního, tak i sekvenčního vykonávání. Zahrnují několik rychlých a škálovatelných kolekcí tříd, zabezpečených pro přístup z více vláken, v oboru názvů System.Collections.Concurrent a několik nových typů synchronizace. Například SemaphoreLock a System.Threading.ManualResetEventSlim, které jsou pro konkrétní druhy pracovního vytížení efektivnější než jejich předchůdci. Další nové typy v rozhraní .NET Framework verze 4, například System.Threading.Barrier a System.Threading.SpinLock, poskytují funkce, které v dřívějších verzích nebyly k dispozici. Další informace naleznete v tématu Struktury dat pro paralelní programování.
Vlastní typy úloh
Doporučujeme, aby nebylo odvozeno od System.Threading.Tasks.Task nebo System.Threading.Tasks.Task<TResult>. Místo toho použijte AsyncState Vlastnost přidružit další data nebo státu s Task nebo Task<TResult> objektu. Rozšíření metody můžete použít také k rozšíření funkcí Task a Task<TResult> tříd. Další informace o metodách rozšíření, viz Extension Methods (C# Programming Guide) a Extension Methods (Visual Basic).
Pokud musí dědit z Task nebo Task<TResult>, nelze použít System.Threading.Tasks.TaskFactory, System.Threading.Tasks.TaskFactory<TResult>, nebo System.Threading.Tasks.TaskCompletionSource<TResult> třídy vytvořit instance typu vlastní úkol, protože tyto třídy vytvořit pouze Task a Task<TResult> objektů. Kromě toho nelze použít mechanismy pokračování úloh poskytnuté Task, Task<TResult>, TaskFactory, a TaskFactory<TResult> vytvořit instance typu vlastní úkol, protože tyto mechanismy také vytvořit pouze Task a Task<TResult> objektů.
Příbuzná témata
Title |
Popis |
Popisuje, jak fungují pokračování. |
|
Popisuje rozdíl mezi podřízenými úlohami a úlohami vnořenými. |
|
Popisuje podporu zrušení, který je integrován Task Třída |
|
Popisuje způsob zpracování výjimek v souběžných vláknech. |
|
Postupy: Použití Parallel.Invoke k vykonávání paralelních operací |
Popisuje, jak použít Invoke. |
Popisuje, jak z úloh vracet hodnoty. |
|
Popisuje, jak čekat na úlohy. |
|
Popisuje, jak zrušit úlohy. |
|
Popisuje způsob zpracování výjimek vyvolaných úlohami. |
|
Popisuje, jak spustit úlohu při dokončení jiné úlohy. |
|
Popisuje jak použit úlohy k procházení binárního stromu. |
|
Popisuje způsob použití For a ForEach pro vytvoření paralelních smyček nad daty. |
|
Pro nejvyšší úroveň uzel.NET paralelního programování. |
Viz také
Koncepty
Paralelní programování v rozhraní .NET Framework
Historie změn
Datum |
Poslední dokumenty |
Důvod |
---|---|---|
Březen 2011 |
Přidány informace o dědí Task a Task<TResult> tříd. |
Rozšíření informace |