Zrušení v knihovně PPL
Tento dokument vysvětluje roli zrušení v knihovně paralelní vzorky (PPL), jak zrušit paralelní práce a jak lze zjistit, kdy je zrušena paralelní práce.
[!POZNÁMKA]
Modul runtime používá zpracování výjimek implementovat zrušení.Skutečné nebo zpracování těchto výjimek v kódu.Kromě toho doporučujeme psát kód výjimky bezpečnost v orgánech funkce pro úkoly.Například můžete použít Inicializace je pořízení prostředků (RAII) vzorek zajistit prostředky jsou při je vyvolána výjimka v těle úkol správně zpracovány.Kompletní příklad, který používá vzorek RAII k vyčištění prostředků vzdálené úlohy, naleznete v Návod: Odstranění práce z vlákna uživatelského rozhraní.
Klíčové body
Zrušení je spolupráce a koordinace mezi kód, který požaduje zrušení a úkol, který reaguje na zrušení zahrnuje.
Pokud je to možné, práci zrušit pomocí tokenů zrušení.Concurrency::cancellation_token třída definuje token zrušení.
Při použití tokenů zrušení použít concurrency::cancellation_token_source::cancel způsobem zrušení inicializace a concurrency::is_task_cancellation_requested a concurrency::cancel_current_task funkce reagovat na zrušení.
Zrušení nedochází ihned.Přestože nová práce není spuštěna, pokud je zrušena úkol nebo skupinu úkolů, aktivní práce musí kontrolovat a reagovat na zrušení.
Pokračování založeného na hodnotách dědí rušícího tokenu, na svou předchozí úlohou.Podle úloh pokračování nikdy dědí token svou předchozí úlohou.
Použití concurrency::cancellation_token:: žádný metoda při volání konstruktoru nebo funkci, která přebírá cancellation_token objekt, ale nechcete, aby operace být stornovatelnou.Navíc pokud nepředáte rušícího tokenu, na concurrency::task konstruktor nebo concurrency::create_task funkce, tento úkol je nevratné.
V tomto dokumentu
Paralelně prováděné stromy
Zrušení paralelních úloh
Zrušení paralelně prováděných úloh pomocí tokenu zrušení
Zrušení paralelně prováděných úloh pomocí metody cancel
Zrušení paralelně prováděných úloh pomocí výjimek
Zrušení paralelních algoritmů
Kdy nepoužívat zrušení
Paralelně prováděné stromy
PPL používá úkolů a skupin úloh Spravovat podrobné úkoly a výpočty.Vnoření skupin úloh do formuláře stromů paralelní práce.Následující ilustrace znázorňuje strom paralelní práce.Na tomto obrázku tg1 a tg2 představuje úkol skupiny; t1, t2, t3, t4, a t5 představují práce skupiny úloh provést.
Následující příklad ukazuje kód, který je potřebné k vytvoření stromu na obrázku.V tomto příkladu tg1 a tg2 jsou concurrency::structured_task_group objekty; t1, t2, t3, t4, and t5 are concurrency::task_handle objects.
// task-tree.cpp
// compile with: /c /EHsc
#include <ppl.h>
#include <sstream>
#include <iostream>
#include <sstream>
using namespace concurrency;
using namespace std;
void create_task_tree()
{
// Create a task group that serves as the root of the tree.
structured_task_group tg1;
// Create a task that contains a nested task group.
auto t1 = make_task([&] {
structured_task_group tg2;
// Create a child task.
auto t4 = make_task([&] {
// TODO: Perform work here.
});
// Create a child task.
auto t5 = make_task([&] {
// TODO: Perform work here.
});
// Run the child tasks and wait for them to finish.
tg2.run(t4);
tg2.run(t5);
tg2.wait();
});
// Create a child task.
auto t2 = make_task([&] {
// TODO: Perform work here.
});
// Create a child task.
auto t3 = make_task([&] {
// TODO: Perform work here.
});
// Run the child tasks and wait for them to finish.
tg1.run(t1);
tg1.run(t2);
tg1.run(t3);
tg1.wait();
}
Můžete použít také concurrency::task_group třídu k vytvoření stromové struktury podobné práce.Concurrency::task třída také podporuje pojem strom práce.Nicméně task strom je strom závislostí.V task stromu, budoucí práce dokončí po aktuální práce.Ve stromové struktuře skupiny úloh vnitřní práce dokončena před vnější práce.Další informace o rozdílech mezi úkoly a skupiny úloh, naleznete v Funkční paralelismus (Concurrency Runtime).
[Nahoře]
Zrušení paralelních úloh
Existuje několik způsobů, jak zrušit paralelní práce.Upřednostňovaným způsobem je použít token zrušení.Skupiny úkolů také podporu concurrency::task_group::cancel metoda a concurrency::structured_task_group::cancel metody.Poslední způsob je vyvolat výjimku v těle funkce pracovního úkolu.Bez ohledu na to, kterou metodu zvolit pochopit, že zrušení nedojde okamžitě.Přestože nová práce není spuštěna, pokud je zrušena úkol nebo skupinu úkolů, aktivní práce musí kontrolovat a reagovat na zrušení.
Další příklady, které zrušit paralelní úlohy naleznete v tématu Návod: Připojení pomocí úloh a žádostí XML HTTP, Postupy: Přerušení paralelní smyčky pomocí zrušení, a Postupy: Přerušení paralelní smyčky pomocí zpracování výjimek.
Zrušení paralelně prováděných úloh pomocí tokenu zrušení
task, task_group, A structured_task_group třídy podporují zrušení prostřednictvím použití tokenů zrušení.Definuje PPL concurrency::cancellation_token_source a concurrency::cancellation_token třídy pro tento účel.Použijete-li ke zrušení práce token zrušení, modul runtime nespustí novou práci, která se k tomuto tokenu přihlásí.Práce, která je již aktivní, může sledovat svůj token zrušení a zastavit, je-li to možné.
Iniciovat zrušení, zavolejte concurrency::cancellation_token_source::cancel metody.Můžete reagovat na zrušení následujícími způsoby:
Pro task objekty, použijte concurrency::is_task_cancellation_requested a concurrency::cancel_current_task funkce.cancel_current_taskZruší aktuální úkol a všechny jeho pokračování založeného na hodnotách. (Zrušení nezruší token je spojeno s úkolem nebo jeho pokračování.)
Skupiny úkolů a paralelní algoritmy, aplikace concurrency::is_current_task_group_canceling zrušení zjistit a vrátit co nejdříve z těla úkolu, pokud tato funkce vrátí funkce true. (Nevyžadují cancel_current_task ze skupiny úloh.)
Následující příklad ukazuje první základní vzor pro zrušení úlohy.Těla úkolu v některých případech kontroluje zrušení uvnitř smyčky.
// task-basic-cancellation.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
#include <sstream>
using namespace concurrency;
using namespace std;
bool do_work()
{
// Simulate work.
wcout << L"Performing work..." << endl;
wait(250);
return true;
}
int wmain()
{
cancellation_token_source cts;
auto token = cts.get_token();
wcout << L"Creating task..." << endl;
// Create a task that performs work until it is canceled.
auto t = create_task([]
{
bool moreToDo = true;
while (moreToDo)
{
// Check for cancellation.
if (is_task_cancellation_requested())
{
// TODO: Perform any necessary cleanup here...
// Cancel the current task.
cancel_current_task();
}
else
{
// Perform work.
moreToDo = do_work();
}
}
}, token);
// Wait for one second and then cancel the task.
wait(1000);
wcout << L"Canceling task..." << endl;
cts.cancel();
// Wait for the task to cancel.
wcout << L"Waiting for task to complete..." << endl;
t.wait();
wcout << L"Done." << endl;
}
/* Sample output:
Creating task...
Performing work...
Performing work...
Performing work...
Performing work...
Canceling task...
Waiting for task to complete...
Done.
*/
cancel_current_task Funkce vyvolá; proto není nutné explicitně vrátit z aktuální smyčky nebo funkce.
Tip
Alternativně můžete volat concurrency::interruption_point namísto funkce is_task_cancellation_requested a cancel_current_task.
Je třeba volat cancel_current_task kdy je odpovídat na zrušení, protože přechází úkol do stavu zrušeno.Pokud vrátíte dříve namísto volání metody cancel_current_task, operaci přechází do dokončeného stavu a jsou spuštěny žádné pokračování založeného na hodnotách.
Upozornění |
---|
Nikdy nevyvolá task_canceled z vašeho kódu.Namísto toho vyvolejte cancel_current_task. |
Po skončení úkolu ve státě zrušeno, concurrency::task::get vyvolá metodu concurrency::task_canceled. (Naopak, concurrency::task::wait vrátí task_status::canceled a nevyvolá.) Následující příklad ukazuje toto chování pro pokračování podle úloh.Pokračování podle úloh je volána vždy, i když předchozí úloha je zrušena.
// task-canceled.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
auto t1 = create_task([]() -> int
{
// Cancel the task.
cancel_current_task();
});
// Create a continuation that retrieves the value from the previous.
auto t2 = t1.then([](task<int> t)
{
try
{
int n = t.get();
wcout << L"The previous task returned " << n << L'.' << endl;
}
catch (const task_canceled& e)
{
wcout << L"The previous task was canceled." << endl;
}
});
// Wait for all tasks to complete.
t2.wait();
}
/* Output:
The previous task was canceled.
*/
Protože hodnota založena pokračování dědí token jejich předchozí úloha, pokud byly vytvořeny s explicitním token, pokračování okamžitě vstoupit do zrušené stavu i v případě závady předchozí úlohy stále probíhá.Proto jakákoli výjimka, která je vyvolána, po zrušení předchozí úlohou není rozšířena do pokračujících úloh.Zrušení vždy přepíše předchozí úloha státu.V následujícím příkladu se podobá předchozí, ale ukazuje chování pro pokračování založeného na hodnotách.
auto t1 = create_task([]() -> int
{
// Cancel the task.
cancel_current_task();
});
// Create a continuation that retrieves the value from the previous.
auto t2 = t1.then([](int n)
{
wcout << L"The previous task returned " << n << L'.' << endl;
});
try
{
// Wait for all tasks to complete.
t2.get();
}
catch (const task_canceled& e)
{
wcout << L"The task was canceled." << endl;
}
/* Output:
The task was canceled.
*/
Upozornění |
---|
Pokud nepředáte rušícího tokenu k task konstruktor nebo concurrency::create_task funkce, tento úkol je nevratné.Kromě toho musí předat stejný token zrušení konstruktoru všech vnořených úloh (to znamená úkoly vytvořené v jiném úkolu) současně zrušit všechny úlohy. |
Je vhodné umožnit spuštění libovolného kódu, když je zrušeno rušícího tokenu.Například, pokud uživatel vybere Zrušit tlačítka v uživatelském rozhraní na tlačítko Storno, může zakázat tlačítko dokud uživatel spustí jinou operaci.Následující příklad ukazuje, jak použít concurrency::cancellation_token::register_callback metody zpětného volání funkce, která se spouští při zrušení token zrušení registrace.
// task-cancellation-callback.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
cancellation_token_source cts;
auto token = cts.get_token();
// An event that is set in the cancellation callback.
event e;
cancellation_token_registration cookie;
cookie = token.register_callback([&e, token, &cookie]()
{
wcout << L"In cancellation callback..." << endl;
e.set();
// Although not required, demonstrate how to unregister
// the callback.
token.deregister_callback(cookie);
});
wcout << L"Creating task..." << endl;
// Create a task that waits to be canceled.
auto t = create_task([&e]
{
e.wait();
}, token);
// Cancel the task.
wcout << L"Canceling task..." << endl;
cts.cancel();
// Wait for the task to cancel.
t.wait();
wcout << L"Done." << endl;
}
/* Sample output:
Creating task...
Canceling task...
In cancellation callback...
Done.
*/
Dokument Funkční paralelismus (Concurrency Runtime) vysvětluje rozdíl mezi hodnoty a úkol pokračování.Pokud nezadáte cancellation_token objekt do pokračovací úlohy pokračování zdědí token zrušení předchozí úloha následujícími způsoby:
Pokračování na základě hodnoty vždy dědí token zrušení úkolu antecedent.
Podle úloh pokračování nikdy dědí token zrušení úkolu antecedent.Jediným způsobem, jak vytvořit pokračování podle úloh cancelable je explicitně předat token zrušení.
Tyto chování nejsou ovlivněny chybovém úkol (to znamená jeden, která vyvolá výjimku).Pokračování na základě hodnoty v tomto případě je zrušena; pokračování podle úloh není zrušeno.
Upozornění |
---|
Úkol, který je vytvořen v jiném úkolu (jinými slovy, vnořená úloha) nedědí rušícího tokenu nadřazeného úkolu.Pouze na základě hodnoty pokračování dědí rušícího tokenu, na svou předchozí úlohou. |
Tip
Použití concurrency::cancellation_token:: žádný metoda při volání konstruktoru nebo funkci, která přebírá cancellation_token objektu a nechcete, aby operace být stornovatelnou.
Můžete také poskytnout token zrušení konstruktoru task_group nebo structured_task_group objektu.Důležitým aspektem tohoto je, že dítě úkol skupiny zdědí tento token zrušení.Pro příklad, který demonstruje tento pojem pomocí concurrency::run_with_cancellation_token k volání funkce parallel_for, viz Zrušení paralelní algoritmy dále v tomto dokumentu.
[Nahoře]
Tokeny zrušení a skládání úloh
Concurrency::when_all a concurrency::when_any funkce může pomoci při vytváření více úkolů provádět běžné vzory.Tato část popisuje, jak tyto funkce pracovat s tokenů zrušení.
Poskytnete-li token zrušení buď when_all a when_any fungovat, že zruší funkce pouze v případě, že dojde ke zrušení token zrušení, nebo pokud jeden účastník končí ve stavu zrušené úkoly nebo vyvolá výjimku.
when_all Funkce dědí z každého úkolu, který vytvoří celkový provoz rušícího tokenu, na něj nezadáte-li rušícího tokenu.Úkol, který je vrácen z when_all je zrušena, pokud všechny tyto tokeny jsou zrušeny a alespoň jeden z účastníků úkolů ještě nebyl spuštěn nebo běží.Podobné chování nastane, pokud jeden z úkolů vyvolá výjimku – úkol, který je vrácen z when_all s výjimkou, že okamžitě zrušena.
Modul runtime rozhodne rušícího tokenu pro úkol, který je vrácen z when_any fungovat při dokončení této úlohy.Pokud žádný z účastníků úkolů do dokončeného stavu dokončení a vyvolá výjimku, jeden nebo více úkolů, je jedním z úkolů, které způsobilo rozhodli Dokončit when_any a jeho token je vybrána jako token pro poslední úkol.Je-li více než jeden úkol končí v kompletní stavu, úkol, který je vrácen z when_any úkol končí na stav dokončeno.Modul runtime pokusí vybrat dokončeného úkolu, jehož token není zrušen v době dokončování tak, aby úkol, který je vrácen z when_any není okamžitě zrušena, i když může být jiné vykonávající úkoly dokončit později.
[Nahoře]
Zrušení paralelně prováděných úloh pomocí metody cancel
Concurrency::task_group::cancel a concurrency::structured_task_group::cancel metody nastavit skupinu úloh do stavu zrušeno.Po volání cancel, skupiny úloh nespustí budoucí úkoly.cancel Metody lze volat více podřízených úkolů.Zrušené úkolu způsobí, že concurrency::task_group::wait a concurrency::structured_task_group::wait metody vrátit concurrency::canceled.
Pokud skupina úloh je zrušena, můžete spustit volání z každého podřízeného úkolu do modulu runtime bod přerušení, což způsobí, že modul runtime vyvolávání a zachycení typem vnitřní výjimky zrušit aktivní úlohy.Modul Runtime souběžnosti nedefinuje konkrétní přerušení bodů; že může dojít v každé volání modulu runtime.Modul runtime musí zpracovat výjimky, které vyvolává mohli provést zrušení.Proto nesprávně zpracovává výjimky Neznámý do těla úkolu.
Pokud podřízená úloha provede časově náročná operace a nevolá do modulu runtime, musí pravidelně kontrolovat zrušení a ukončení v časovém limitu.Následující příklad ukazuje jeden způsob, jak zjistit, kdy je zrušena práce.Úkol t4 zruší nadřazené skupiny úloh, když narazí na chybu.Úkol t5 občas volá structured_task_group::is_canceling metodu ke kontrole zrušení.Pokud je zrušeno nadřazené skupiny úloh, úloh t5 vytiskne zprávu a ukončí.
structured_task_group tg2;
// Create a child task.
auto t4 = make_task([&] {
// Perform work in a loop.
for (int i = 0; i < 1000; ++i)
{
// Call a function to perform work.
// If the work function fails, cancel the parent task
// and break from the loop.
bool succeeded = work(i);
if (!succeeded)
{
tg2.cancel();
break;
}
}
});
// Create a child task.
auto t5 = make_task([&] {
// Perform work in a loop.
for (int i = 0; i < 1000; ++i)
{
// To reduce overhead, occasionally check for
// cancelation.
if ((i%100) == 0)
{
if (tg2.is_canceling())
{
wcout << L"The task was canceled." << endl;
break;
}
}
// TODO: Perform work here.
}
});
// Run the child tasks and wait for them to finish.
tg2.run(t4);
tg2.run(t5);
tg2.wait();
Tento příklad zkontroluje pro zrušení na každých 100th opakování úkolu smyčky.Frekvence, s jakou kontrolovat zrušení závisí na množství práce, kterou úloha provádí a jak rychle potřebujete pro úkoly, které mají reagovat na zrušení.
Pokud nemáte přístup k objektu nadřazené skupiny úloh, volat concurrency::is_current_task_group_canceling funkce k určení, zda je zrušena nadřazené skupiny úloh.
cancel Metoda ovlivní pouze podřízené úlohy.Například, pokud zrušíte úkol skupiny tg1 na obrázku stromu paralelní práce všechny úkoly ve stromu (t1, t2, t3, t4, a t5) jsou ovlivněny.Při zrušení skupiny vnořených úloh, tg2, pouze úlohy t4 a t5 jsou ovlivněny.
Při volání cancel metoda, skupiny jsou také zrušena všechna podřízená úloha.Zrušení neovlivní žádné rodiče ve stromové struktuře paralelní pracovní skupiny úloh.Následující příklady ukazují to tak, že na obrázek stromu paralelní práce.
První z těchto příkladů vytváří funkci pracovního úkolu t4, který je podřízený úkol skupiny tg2.Pracovní funkce volá funkci work ve smyčce.Žádné volání na work nezdaří úloha zruší nadřazené skupině úloh.To způsobí, že úkol skupiny tg2 do stavu zrušeno, ale nezruší skupiny úloh tg1.
auto t4 = make_task([&] {
// Perform work in a loop.
for (int i = 0; i < 1000; ++i)
{
// Call a function to perform work.
// If the work function fails, cancel the parent task
// and break from the loop.
bool succeeded = work(i);
if (!succeeded)
{
tg2.cancel();
break;
}
}
});
Tento druhý příklad je podobný první z nich, s tím rozdílem, že úloha zruší skupina úloh tg1.This affects all tasks in the tree (t1, t2, t3, t4, and t5).
auto t4 = make_task([&] {
// Perform work in a loop.
for (int i = 0; i < 1000; ++i)
{
// Call a function to perform work.
// If the work function fails, cancel all tasks in the tree.
bool succeeded = work(i);
if (!succeeded)
{
tg1.cancel();
break;
}
}
});
structured_task_group Třída není podproces bezpečné.Proto podřízená úloha který volá metodu svého rodiče structured_task_group vytváří objekt neurčené chování.Výjimky z tohoto pravidla jsou structured_task_group::cancel a concurrency::structured_task_group::is_canceling metody.Podřízená úloha může tyto metody volat a zrušit nadřazené skupiny úkolů a kontrolovat zrušení.
Upozornění |
---|
Přestože rušícího tokenu lze použít ke zrušení práce, kterou provádí skupina úloh, která se spouští jako podřízený task objektu nelze použít task_group::cancel nebo structured_task_group::cancel metody zrušit task objekty, které jsou ve skupině úloh spustit. |
[Nahoře]
Zrušení paralelně prováděných úloh pomocí výjimek
Použití tokenů zrušení a cancel metody jsou efektivnější než na zrušení stromu paralelní práce pro zpracování výjimek.Tokenů zrušení a cancel metoda zrušit úlohu a všechny podřízené úkoly způsobem shora dolů.Zpracování výjimek naopak funguje způsobem zdola nahoru a zrušit každou podřízenou skupinu úloh samostatně jako výjimka se šíří směrem nahoru.Téma Zpracování výjimek v Concurrency Runtime popisuje, jak modul Runtime souběžnosti používá ke komunikaci chyby výjimky.Nicméně ne všechny výjimky udávající chybu.Algoritmus vyhledávání může například zrušit jeho přidruženého úkolu, pokud nalezne výsledek.Jak již bylo zmíněno dříve, zpracování výjimek je však méně efektivní než použití cancel metoda zrušit paralelní práce.
Upozornění |
---|
Doporučujeme používat výjimky pro paralelní práci pouze v případě, že je nezbytné zrušit.Tokenů zrušení a skupiny úloh cancel metody jsou efektivnější a méně náchylné k chybě. |
Když je výjimku v těle funkce práce, který předáte do skupiny úloh, modul runtime ukládá tato výjimka a zařazuje výjimku z kontextu, který čeká skupina úkolů k dokončení.Stejně jako cancel metody, modul runtime zahodí všechny úkoly, které nebyly ještě nezačala a přestane přijímat nové úkoly.
Tento třetí příklad druhý, s výjimkou tohoto úkolu se podobá t4 vyvolá výjimku zrušit úkol skupiny tg2.V tomto příkladu try-catch blokovat, jestliže chcete kontrolovat zrušení při skupiny úloh tg2 čeká na své podřízené úkoly do konce.Stejně jako v prvním příkladu, to způsobí, že úkol skupiny tg2 do stavu zrušeno, ale nezruší skupiny úloh tg1.
structured_task_group tg2;
// Create a child task.
auto t4 = make_task([&] {
// Perform work in a loop.
for (int i = 0; i < 1000; ++i)
{
// Call a function to perform work.
// If the work function fails, throw an exception to
// cancel the parent task.
bool succeeded = work(i);
if (!succeeded)
{
throw exception("The task failed");
}
}
});
// Create a child task.
auto t5 = make_task([&] {
// TODO: Perform work here.
});
// Run the child tasks.
tg2.run(t4);
tg2.run(t5);
// Wait for the tasks to finish. The runtime marshals any exception
// that occurs to the call to wait.
try
{
tg2.wait();
}
catch (const exception& e)
{
wcout << e.what() << endl;
}
Tento čtvrtý příklad používá zpracování výjimek zrušit stromu celé práce.Příklad zachytí výjimku při úkol skupiny tg1 skupiny úkolů čeká jeho podřízené úlohy dokončit místo při tg2 čeká jeho podřízených úloh.Jako druhý příklad, to způsobí, že obě skupiny úkolů ve stromu, tg1 a tg2, vstoupit do stavu zrušeno.
// Run the child tasks.
tg1.run(t1);
tg1.run(t2);
tg1.run(t3);
// Wait for the tasks to finish. The runtime marshals any exception
// that occurs to the call to wait.
try
{
tg1.wait();
}
catch (const exception& e)
{
wcout << e.what() << endl;
}
Protože task_group::wait a structured_task_group::wait vyvoláním metody Pokud podřízená úloha vyvolá výjimku, není vrácená hodnota od nich obdržíte.
[Nahoře]
Zrušení paralelních algoritmů
Paralelní algoritmy v PPL, například parallel_for, vytvoření skupiny úkolů.Proto můžete mnoho stejných postupů pro zrušení paralelního algoritmu.
Následující příklady ilustrují několik způsobů, jak zrušit paralelní algoritmus.
V následujícím příkladu run_with_cancellation_token funkce pro volání parallel_for algoritmu.run_with_cancellation_token Funkce přijímá zrušení token jako argument a volá funkci zadané pracovní synchronně.Vzhledem k tomu, že paralelní algoritmy jsou založeny na úkoly, zdědí rušícího tokenu nadřazeného úkolu.Proto parallel_for může reagovat na zrušení.
// cancel-parallel-for.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
#include <sstream>
using namespace concurrency;
using namespace std;
int wmain()
{
// Call parallel_for in the context of a cancellation token.
cancellation_token_source cts;
run_with_cancellation_token([&cts]()
{
// Print values to the console in parallel.
parallel_for(0, 20, [&cts](int n)
{
// For demonstration, cancel the overall operation
// when n equals 11.
if (n == 11)
{
cts.cancel();
}
// Otherwise, print the value.
else
{
wstringstream ss;
ss << n << endl;
wcout << ss.str();
}
});
}, cts.get_token());
}
/* Sample output:
15
16
17
10
0
18
5
*/
V následujícím příkladu concurrency::structured_task_group::run_and_wait metoda volání parallel_for algoritmu.structured_task_group::run_and_wait Metoda čeká na dokončení zadané úlohy.structured_task_group Objekt umožňuje funkci práce zrušit úlohu.
// To enable cancelation, call parallel_for in a task group.
structured_task_group tg;
task_group_status status = tg.run_and_wait([&] {
parallel_for(0, 100, [&](int i) {
// Cancel the task when i is 50.
if (i == 50)
{
tg.cancel();
}
else
{
// TODO: Perform work here.
}
});
});
// Print the task group status.
wcout << L"The task group status is: ";
switch (status)
{
case not_complete:
wcout << L"not complete." << endl;
break;
case completed:
wcout << L"completed." << endl;
break;
case canceled:
wcout << L"canceled." << endl;
break;
default:
wcout << L"unknown." << endl;
break;
}
Tento příklad vytvoří následující výstup.
Následující příklad používá zpracování výjimek pro zrušení parallel_for smyčky.Modul runtime zařazuje výjimku v kontextu volajícího.
try
{
parallel_for(0, 100, [&](int i) {
// Throw an exception to cancel the task when i is 50.
if (i == 50)
{
throw i;
}
else
{
// TODO: Perform work here.
}
});
}
catch (int n)
{
wcout << L"Caught " << n << endl;
}
Tento příklad vytvoří následující výstup.
Následující příklad používá logické příznak ke zrušení v koordinaci parallel_for smyčky.Každý úloha spuštěna, protože není použita v tomto příkladu cancel metoda nebo výjimka zpracování zrušit celkovou sadu úkolů.Tato technika tedy může mít více výpočetních režii než mechanismus zrušení.
// Create a Boolean flag to coordinate cancelation.
bool canceled = false;
parallel_for(0, 100, [&](int i) {
// For illustration, set the flag to cancel the task when i is 50.
if (i == 50)
{
canceled = true;
}
// Perform work if the task is not canceled.
if (!canceled)
{
// TODO: Perform work here.
}
});
Každá metoda zrušení má výhody oproti ostatním.Zvolte metodu, která odpovídá vašim konkrétním potřebám.
[Nahoře]
Kdy nepoužívat zrušení
Zrušení používání je vhodné v případě, že každý člen skupiny souvisejících úloh lze ukončit včas.Existují však některé scénáře, kde zrušení nemusí být vhodné pro vaši aplikaci.Například protože je kooperativní zrušení úlohy, celkovou sadu úkolů se zruší, pokud všechny jednotlivé úkoly je blokován.Například pokud jeden úkol ještě nebyl zahájen, ale je aktivní jiný úkol odblokuje, se nespustí Pokud skupina úloh je zrušen.To může způsobit zablokování aplikace.Druhý příklad, kde nemusí být vhodné použití zrušení je úloha je zrušena, ale jeho podřízená úloha provádí důležité operace, jako je například uvolnění prostředku.Vzhledem k tomu, že celkové uvedených úkolů je zrušena, pokud nadřazená úloha zruší, operace se neprovede.To znázorňuje příklad, viz Principy jak zrušení a výjimka zpracování zničení objektu ovlivnit sekce v osvědčených postupů v tématu paralelní knihovnu vzorků.
[Nahoře]
Příbuzná témata
Title |
Description |
---|---|
Ukazuje, jak použít k implementaci algoritmu paralelního vyhledávání zrušení. |
|
Postupy: Přerušení paralelní smyčky pomocí zpracování výjimek |
Ukazuje, jak použít task_group třídy psát vyhledávací algoritmus pro základní stromové struktury. |
Popisuje, jak modul runtime zpracovává výjimky, které jsou vyvolány skupiny úloh, lehké úkoly a asynchronní agentů a jak reagovat na výjimky v aplikacích. |
|
Popisuje, jak souvisí úkoly skupiny úkolů a jak lze použít nestrukturované a strukturované úkoly ve vašich aplikacích. |
|
Popisuje paralelní algoritmy, které souběžně provádět práce na kolekcí dat. |
|
Poskytuje přehled o knihovně paralelní vzorky. |
Odkaz
task – třída (Concurrency Runtime)