Отмена в библиотеке параллельных шаблонов
Этот документ описывает роль отмена в библиотеке параллельных шаблонов (PPL), например отмены параллельной работы, и о том, как определить, когда рабочий параллельных отменен.
![]() |
---|
Среда выполнения использует обработку исключений для реализации отмены.Не перехватывайте и не обрабатывайте эти исключения в своем коде.Кроме того, рекомендуется в теле функций для ваших задач писать код, безопасный в отношении исключений.Например, можно использовать шаблон Получение ресурса есть инициализация (Resource Acquisition Is Initialization, RAII) для обеспечения корректной обработки ресурсов при возникновении исключения в теле задачи.Полный пример с использованием шаблона RAII для очистки ресурса в отменяемой задаче см. в разделе Пошаговое руководство. Удаление задач из потоков пользовательского интерфейса. |
Ключевых этапах
Отмена выполняется совместно и обеспечивает координацию между кодом, который запрашивает отмену и задачу, которая отвечает на отмену.
По возможности следует использовать токены отмены для отмены работы.Класс concurrency::cancellation_token определяет токен отмены.
При использовании токены отмены, используйте метод concurrency::cancellation_token_source::cancel инициировать отмену и функции concurrency::is_task_cancellation_requested и concurrency::cancel_current_task, чтобы реагировать на отмену.
Отмена не происходит немедленно.Хотя создать действие не запущена, если задача или группа целевого назначения отменяется, то активный рабочий должно проверять и реагировать на отмену.
Value-of, основанное продолжение наследует токен отмены его задачи, предшествующей задачи.Задача-, основанное на продолжение никогда не наследует токен своей задачи предшествующей задачи.
Используйте метод concurrency::cancellation_token::none при вызове или действуете конструктор, который принимает объект cancellation_token но оно должно быть cancellable операцию.Кроме того, если токен отмены не передается конструктору concurrency::task или функции concurrency::create_task, то эта задача не cancellable.
в этом документе
Деревья параллельной работы
Отмена параллельных задач
С помощью токена отмены для отмены параллельной работы
Использование метода cancel для отмены параллельной работы
Использование исключений для отмены параллельной работы
Отмена параллельных алгоритмов
Когда не следует использовать отмену
Деревья параллельной работы
PPL использует задачи и группы целевого назначения управления тонкозернистые задачи и вычислений.Можно вкладывать группы задач одна в другую, чтобы создавать деревья параллельной работы.На следующем рисунке показано дерево параллельной работы.На этом рисунке tg1 и tg2 представляющие группы целевого назначения; t1, t2, t3, t4 и t5 представляющие работу, группы выполняют целевого назначения.
В следующем примере показан код, необходимый для создания дерева, изображенного на рисунке.В этом примере tg1 и tg2 объекты concurrency::structured_task_group; t1, t2, t3, t4 и t5 объекты concurrency::task_handle.
// 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();
}
Также можно использовать класс concurrency::task_group для создания подобного дерево действий.Класс concurrency::task также поддерживает понятие дерева действий.Однако дерево task дерево зависимостей.В дереве task, будущие рабочие завершаются после текущего рабочего процесса.В дереве групп целевого назначения внутренний работы перед внешним исполнителем.Дополнительные сведения о различиях между задачами и группами целевого назначения см. в разделе Параллелизм задач (среда выполнения с параллелизмом).
[Верх]
Отмена параллельных задач
Существует несколько способов отмены параллельной работы.Предпочтительный способ - использовать токен отмены.Группы целевого назначения также поддерживает метод concurrency::task_group::cancel и метод concurrency::structured_task_group::cancel.Последний способ вызова исключения в теле рабочей функции задачи.Нет дела, метод можно выбрать, понимает, что отмена не происходит немедленно.Хотя создать действие не запущена, если задача или группа целевого назначения отменяется, то активный рабочий должно проверять и реагировать на отмену.
Дополнительные примеры, отменять параллельные задачи см. в разделе Пошаговое руководство. Подключение с использованием задач и HTTP-запроса XML (IXHR2), Практическое руководство. Использование отмены для выхода из параллельного цикла и Практическое руководство. Использование обработки исключений для выхода из параллельного цикла.
С помощью токена отмены для отмены параллельной работы
task, task_group и классы structured_task_group поддерживают отмену посредством использования маркеров " отмена ".PPL определяет классы concurrency::cancellation_token_source и concurrency::cancellation_token для этой цели.При использовании токен отмены, чтобы отменить работу, среда выполнения не начинает новую работа этой подписки к токену.Работа, уже активно может отслеживать ее токена отмены и останавливаться, когда он может.
Чтобы инициировать отмену, вызовите метод concurrency::cancellation_token_source::cancel.Вы отвечаете на отмену следующим образом:
Для объектов task используйте функции concurrency::is_task_cancellation_requested и concurrency::cancel_current_task.cancel_current_task отменяет текущую задачу и любой из его value-of на основе продолжений.(Он не отменяет токен отмены, связанный с задачей или его продолжениями).
Для групп целевого назначения и параллельных алгоритмов, используйте функцию concurrency::is_current_task_group_canceling для обнаружения отмена и возвращать как можно быстрее из тела задачи, когда эта функция возвращает true.(Не вызывайте cancel_current_task из группы целевого назначения).
В следующем примере показан первый базовый шаблон для отмены задачи.Тело задачи периодически проверяет отмены внутри цикла.
// 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; следовательно, не требуется явно возвращать из текущего цикла или функции.
![]() |
---|
Кроме того, можно вызвать функцию concurrency::interruption_point вместо is_task_cancellation_requested и cancel_current_task. |
Важно вызвать cancel_current_task при отвечаете на отмену, поскольку задача переходит в состояние canceled.Если возвращается раньше, то вместо вызова cancel_current_task переходы выполняются операции в завершенное состояние и все основанные value-of продолжения.
![]() |
---|
Никогда не бросайте task_canceled из программного кода.Вызов cancel_current_task. |
Окончания задачи в отмененном состоянии concurrency::task::get вызывают метод concurrency::task_canceled.(И наоборот, concurrency::task::wait возвращает task_status::canceled и не вызывает исключение). Следующий пример иллюстрирует эту расширение функциональности для задача-, основываясь продолжения.Задача-, основанное на продолжение всегда вызывается, даже когда задача предшествующей задачи будет отменена.
// 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.
*/
Поскольку value-of на основе наследуют свои задачи продолжения токен предшествующей задачи, если они не будут созданы с явно указанным токеном, продолжений вставить непосредственно отмененному состояние даже если задача предшествующей задачи по-прежнему выполняется.Следовательно, любое исключение, которое вызывается задачей предшествующей задачи после отмены не распространяется на продолжение задает действие.Отмена всегда переопределяет состояние задачи предшествующей задачи.Следующий пример похож на предыдущий, но демонстрирует расширение функциональности для value-of, основываясь продолжения.
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.
*/
![]() |
---|
Если токен отмены не передается конструктору task или функции concurrency::create_task, то эта задача не cancellable.Кроме того, необходимо передать один и тот же токен отмены конструктору всех вложенных задач (то есть задач, которые создаются в теле другой задачи) отменить все задачи за раз. |
Может возникнуть необходимость выполнять произвольный код в тех случаях, когда токен отмены будет отменен.Например, если пользователь выбирает кнопку Отмена в пользовательском интерфейсе для отмены операции, то можно отключить эту кнопку, пока пользователь не сможет запустить другая операция.В следующем примере показано, как использовать метод concurrency::cancellation_token::register_callback чтобы зарегистрировать функцию обратного вызова, которая выполняется при отмене токена отмены.
// 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.
*/
Документ Параллелизм задач (среда выполнения с параллелизмом) объясняет разницу между value-of и задача- на основе на продолжениями.Если не указать объект cancellation_token в задачу продолжения, продолжение наследует от предшествующей задачи токен отмены задачи следующими способами:
Value-of, основанное на продолжение всегда наследует токен отмены задачи предшествующей задачи.
Задача-, основанное на продолжение никогда не наследует токен отмены задачи предшествующей задачи.Единственным способом сделать задача-, основанное на продолжение отменяемым явно передавать токен отмены.
Эти расширения функциональности не затронуты faulted задачей (то есть одно исключение, которое вызывает).В этом случае value-of, основанное на продолжение отменено; задача-, основанное на продолжение не отменено.
![]() |
---|
Задача, которая создается в другой задаче (иначе говоря, вложенные задаче) не наследует токен отмены родительской задачи.Только value-of токен отмены, основанное на продолжение наследует его задачи, предшествующей задачи. |
![]() |
---|
Используйте метод concurrency::cancellation_token::none при вызове или действуете конструктор, который принимает объект cancellation_token и не должен быть cancellable операцию. |
Кроме того, можно реализовывать токен отмены конструктор объекта task_group или structured_task_group.Важным аспектом этого, что группы целевого назначения дочернего элемента наследующие этот токен отмены.Пример, демонстрирующий эту концепцию с помощью функции concurrency::run_with_cancellation_token выполнения для вызова parallel_for см. в разделе Отмена параллельных алгоритмов позднее в этом документе.
[Верх]
Токены отмены и композиция задачи
Функции concurrency::when_all и concurrency::when_any помогут сочетать несколько задач реализации общих шаблонов.Этот раздел описывает, как эти функции работают с токенами отмены.
При снабубежите токен отмены любой функции when_all и when_any эта функция отменяет, только если этот токен отмены прерван или когда один из концов задач элемента в отмененном состоянии или вызывает исключение.
Функция when_all наследует токен отмены из каждой задачи, которая образует общую операцию, если не снабубежите токен отмены.Задача отменена, которое возвращается из when_all если любая из этих токены отменяются и хотя бы один из элементов задачи еще не начат или запущены.Подобная реакция на событие происходит, когда одна из задач вызывает исключение – задача, которая возвращается из when_all немедленно отменена с этим исключением.
Среда выполнения выбирает токен отмены задачи, которая возвращается из функции when_any, когда эта задача завершается.Если ни одна из задач элемента завершатся в завершенном состоянии и одну или несколько задач вызывают исключение, задач, бросили выбрать для завершения when_any и его токен выбрано как маркер для последней задачей.Если более чем одна задача завершается в завершенном состоянии, то задача, которая возвращается из концов задачи when_any в завершенном состоянии.Попытки среды выполнения для выбора завершенная задача токен которой не будет отменена во время выполнения, чтобы задача, которая возвращается из when_any не будут отменены, даже если остальные при выполнении задачи могут завершиться на более последний шаг.
[Верх]
Использование метода cancel для отмены параллельной работы
Методы concurrency::task_group::cancel и concurrency::structured_task_group::cancel задать группу целевого назначения в состояние canceled.После вызова метода cancel группа задач не начинает выполнение следующих задач.Методы cancel могут вызываться несколькими дочерними задачами.Задача отменена concurrency::task_group::wait и вызывает методы concurrency::structured_task_group::wait возвращать concurrency::canceled.
Если группа задач отменяется, вызовы в среде выполнения, совершаемые каждой дочерней задачей, могут инициировать точку прерывания, которая заставляет среду выполнения создавать и перехватывать тип внутреннего исключения для отмены активных задач.Среда выполнения с параллелизмом не определяет конкретные точки прерывания; они могут находиться в любом вызове среды выполнения.Чтобы выполнить отмену, среда выполнения должна обработать созданные ею исключения.Поэтому не следует обрабатывать неизвестные исключения в теле задачи.
Если дочерняя задача выполняет времязатратную операцию и не совершает вызов в среде выполнения, она должна периодически проверять отмену и своевременно выполнять выход.В следующем примере показан один из способов определить отмену работы.Задача t4 отменяет родительскую группу задач при обнаружении ошибки.Задача t5 периодически вызывает метод structured_task_group::is_canceling для проверки отмены.Если родительская группа задач отменяется, задача t5 выводит сообщение и выполняет выход.
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();
В этом примере проверка отмены выполняется каждую сотую итерацию цикла задач.Частота проверки отмены зависит от объема работы, выполняемой задачей, и тем, насколько быстро задачи должны реагировать на отмену.
При отсутствии доступа к родительскому объекту группы целевого назначения, вызовите функцию concurrency::is_current_task_group_canceling, чтобы определить, отменена ли родительская группа целевого назначения.
Метод cancel влияет только на дочерние задачи.Например, если отменить группу задач tg1 на рисунке дерева параллельной работы, это повлияет на все задачи в этом дереве (t1, t2, t3, t4 и t5).Если отменить вложенную группу задач, tg2, это повлияет только на задачи t4 и t5.
При вызове метода cancel также отменяются все дочерние группы задач.Однако отмена не влияет ни на какие родительские элементы группы задач в дереве параллельной работы.В следующих примерах это показано на рисунке дерева параллельной работы.
В первом из этих примеров создается рабочая функция для задачи t4, которая является дочерним элементом группы задач tg2.Рабочая функция вызывает функцию work в цикле.Если какой-либо вызов work дает сбой, задача отменяет свою родительскую группу задач.После этого группа задач tg2 переходит в отмененное состояние, но при этом не отменяется группа задач 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;
}
}
});
Второй пример аналогичен первому за исключением того, что задача отменяет группу задач tg1.Это влияет на все задачи в дереве (t1, t2, t3, t4 и 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 не является потокобезопасным.Следовательно, дочерняя задача, вызывающая метод своего родительского объекта structured_task_group, может стать причиной непредсказуемого поведения.Исключения из этого правила являются методы structured_task_group::cancel и concurrency::structured_task_group::is_canceling.Задача дочернего элемента может вызывать эти методы, чтобы отменить родительскую группу целевого назначения и проверка отмены.
![]() |
---|
Хотя можно использовать токен отмены, чтобы отменить работу, выполняется группой целевого назначения, которая выполняется как дочерний элемент объекта task, нельзя использовать методы task_group::cancel или structured_task_group::cancel для отмены объектов task, выполняемых в группе целевого назначения. |
[Верх]
Использование исключений для отмены параллельной работы
Использование маркеров отмены и метод cancel более эффективным, чем обработка исключений для отмены дерево параллельной работы.Токены отмены и метод отменяет cancel задачи, и все задачи дочерних элементов последовательно сверху вниз.Напротив, обработка исключений осуществляется снизу вверх. При этом каждую дочернюю группу задач необходимо отменять отдельно, так как исключение распространяется вверх.В разделе Обработка исключений в среде выполнения с параллелизмом объясняется, как в среде выполнения с параллелизмом для сообщения об ошибках используются исключения.Однако не все исключения указывают на ошибку.Например, алгоритм поиска может отменить связанная с ним задачу при обнаружении результат.Однако как упоминалось ранее, обработка исключений является менее эффективным методом отмены параллельной работы, чем метод cancel.
![]() |
---|
Рекомендуется использовать исключений для отмены параллельной работы только в случае необходимости.Токены отмены и методы cancel группы целевого назначения более эффективными и менее прональны к ошибке. |
При создании исключения в теле рабочей функции, передаваемой группе задач, среда выполнения хранит это исключение и маршалирует его в контекст, ожидающий завершения группы задач.Как и в случае с методом cancel среда выполнения удаляет любые задачи, выполнение которых еще не было начато, и не принимает новые задачи.
Третий пример напоминает второй за исключением того, что задача t4 создает исключение для отмены группы задач tg2.В этом примере блок try-catch используется для проверки отмены, когда группа задач tg2 ожидает завершения дочерних задач.Как и в первом примере, после этого группа задач tg2 переходит в отмененное состояние, но при этом не отменяется группа задач 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;
}
В четвертом примере обработка исключений используется для отмены всего дерева работы.В этом примере перехватывается исключение, когда завершения дочерних задач ожидает группа задач tg1, а не tg2.Как и во втором примере, из-за этого обе группы задач в дереве (tg1 и tg2) переходят в отмененное состояние.
// 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;
}
Поскольку методы task_group::wait и structured_task_group::wait создают исключение, когда создает исключение дочерняя задача, пользователь не получает от них возвращаемого значения.
[Верх]
Отмена параллельных алгоритмов
Параллельные алгоритмы in the PPL, например, parallel_for, построение на группах целевого назначения.Следовательно, для отмены параллельного алгоритма можно использовать многие из описанных методов.
В следующих примерах показано несколько способов отмены параллельного алгоритма.
Следующий пример использует функцию run_with_cancellation_token для вызова алгоритм parallel_for.Функция принимает в качестве аргумента run_with_cancellation_token токен отмены и вызывается заданная рабочая функция одновременно.Поскольку параллельные алгоритмы строятся на задачах, их наследуют токен отмены родительской задачи.Поэтому parallel_for может реагировать на отмену.
// 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
*/
В следующем примере используется метод concurrency::structured_task_group::run_and_wait для вызова алгоритм parallel_for.Метод structured_task_group::run_and_wait ожидает завершения предоставленной задачи.Объект structured_task_group позволяет рабочей функции отменить задачу.
// 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;
}
В результате выполнения примера получается следующий результат:
The task group status is: canceled.
В следующем примере обработка исключений используется для отмены цикла parallel_for.Среда выполнения маршалирует исключение в контекст вызова.
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;
}
В результате выполнения примера получается следующий результат:
Caught 50
В следующем примере логический флаг координирует отмену в цикле parallel_for.Выполняется каждая задача, потому что в этом примере общий набор задач не отменяется с помощью метода cancel или обработки исключений.Таким образом, использование этой техники создает большую вычислительную нагрузку на систему, чем механизм отмены.
// 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.
}
});
Каждый метод отмены имеет свои преимущества.Необходимо выбирать метод, соответствующий конкретным потребностям пользователя.
[Верх]
Когда не следует использовать отмену
Отмену можно использовать, когда каждый член группы связанных задач может своевременно выполнить выход.Однако в некоторых сценариях приложение не позволяет использовать отмену.Например, поскольку отмена задач осуществляется совместно, общий набор задач не будет отменен, если одна из задач заблокирована.Например, если выполнение одной из задач не было начато, но эта задача разблокирует другую активную задачу, выполнение не начнется, если группа задач отменена.Это может стать причиной возникновения в приложении взаимоблокировки.Еще один пример ситуации, когда использование отмены может быть неуместно: задача отменяется, но ее дочерняя задача выполняет важную операцию, например высвобождение ресурса.Так как при отмене родительской задачи отменяется весь набор задач, эта операция выполнена на будет.Пример, иллюстрирующий этот случай, см. в подразделе Understand how Cancellation and Exception Handling Affect Object Destruction раздела "Рекомендации по использованию библиотеки параллельных шаблонов".
[Верх]
Связанные разделы
Заголовок |
Описание |
---|---|
Практическое руководство. Использование отмены для выхода из параллельного цикла |
Показывает использование отмены для реализации алгоритма параллельного поиска. |
Практическое руководство. Использование обработки исключений для выхода из параллельного цикла |
Показано, как использовать класс task_group для записи алгоритм поиска для базовой структуры дерева. |
Описывает обработку в среде выполнения исключений, созданных группами задач, упрощенными задачами и асинхронными агентами, а также реагирование на исключения в приложениях. |
|
Описывает, как задачи связаны с группами задач и как использовать в приложениях неструктурированные и структурированные задачи. |
|
Описывает параллельные алгоритмы, одновременно выполняющие работу с коллекциями данных. |
|
Содержит общие сведения о библиотеке параллельных шаблонов. |
Ссылки
Класс task (среда выполнения с параллелизмом)