PPL에서의 취소

이 문서는 병렬 패턴 라이브러리 (PPL), 병렬 작업을 취소 하는 방법 및 병렬 작업 취소 되는 경우를 확인 하는 방법에 대 한 취소의 역할을 설명 합니다.

[!참고]

런타임은 예외 처리를 사용하여 취소를 구현합니다.코드에서 이러한 예외를 catch하거나 처리하지 마십시오.또한 작업을 위한 함수 본문에 예외로부터 안전한 코드를 작성하는 것이 좋습니다.예를 들어 작업 본문에서 예외가 throw될 때 리소스가 올바르게 처리되도록 하기 위해 RAII(Resource Acquisition Is Initialization) 패턴을 사용할 수 있습니다.RAII 패턴을 사용하여 취소 가능한 작업에서 리소스를 정리하는 예제를 전체적으로 보려면 연습: 사용자 인터페이스 스레드에서 작업 제거를 참조하십시오.

주요 사항

  • 취소 하지 및 취소를 요청 하는 코드 작업을 취소 하려면 응답 사이의 조정 작업이 포함 됩니다.

  • 가능 하면 작업을 취소 하려면 취소 토큰을 사용 합니다.Concurrency::cancellation_token 클래스는 취소 토큰을 정의 합니다.

  • 취소 토큰을 사용 하는 경우 사용 하는 concurrency::cancellation_token_source::cancel 취소를 시작 하는 메서드 및 concurrency::is_task_cancellation_requestedconcurrency::cancel_current_task 취소에 응답할 수 있는 기능.

  • 취소를 즉시 발생 하지 않습니다.작업 또는 작업 그룹을 취소 하면 새 작업 시작 되지만 현재 작업 확인 하 고 응답을 취소 합니다.

  • 값에 따라 연속 선행 작업 취소 토큰을 상속합니다.작업 기반 연속 절대로 해당 선행 작업의 토큰을 상속합니다.

  • 사용은 concurrency::cancellation_token:: 없음 생성자 또는 사용 하는 함수를 호출 하면 메서드는 cancellation_token 개체 있지만 하지 않을 작업을 취소할 수 있습니다.또한 취소 토큰을 전달 하지 않을 경우는 concurrency::task 생성자 또는 concurrency::create_task 함수가 해당 작업이 아닌 취소할 수 있습니다.

이 문서에서

  • 병렬 작업 트리

  • 병렬 작업 취소

    • 취소 토큰을 사용 하 여 병렬 작업 취소

    • cancel 메서드를 사용하여 병렬 작업 취소

    • 예외를 사용하여 병렬 작업 취소

  • 병렬 알고리즘 취소

  • 취소를 사용하지 않는 경우

병렬 작업 트리

PPL을 계산 하 고 세밀 한 작업을 관리할 수 작업 및 작업 그룹을 사용 합니다.작업 그룹을 중첩시켜 병렬 작업의 트리를 구성할 수 있습니다.다음 그림에서는 병렬 작업 트리를 보여 줍니다.이 그림에서 tg1tg2 나타내는 작업 그룹입니다. t1t2, t3, t4, 및 t5 작업 그룹에서 수행 하는 작업을 나타냅니다.

병렬 작업 트리

다음 예제에서는 그림의 트리를 만드는 데 필요한 코드를 보여 줍니다.이 예제에서 tg1tg2concurrency::structured_task_group 개체입니다. 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();   
}

도 수는 concurrency::task_group 유사한 작업 트리를 만들려면 클래스.Concurrency::task 클래스는 작업 트리 개념이 지원 됩니다.그러나는 task 종속성 트리를 트리입니다.에 task 트리, 향후 작동 완료 후 현재 작업.작업 그룹 트리에서 외부 작업 전에 내부 작업을 완료합니다.작업 및 작업 그룹의 차이점에 대 한 자세한 내용은 작업 병렬 처리(동시성 런타임).

Top

병렬 작업 취소

병렬 작업을 취소 하는 여러 가지가 있습니다.취소 토큰을 사용 하는 것이 좋습니다.또한 지원 작업 그룹의 concurrency::task_group::cancel 메서드 및 concurrency::structured_task_group::cancel 메서드.작업 작업 함수 본문에서 예외가 발생 하는 최종 좋습니다.어떤 방법을 선택 하더라도 취소 즉시 발생 하지 않는 것을 이해 합니다.작업 또는 작업 그룹을 취소 하면 새 작업 시작 되지만 현재 작업 확인 하 고 응답을 취소 합니다.

병렬 작업을 취소 하는 자세한 예제를 보려면 연습: 작업 및 XML HTTP 요청(IXHR2)을 사용하여 연결, 방법: 취소를 사용하여 병렬 루프 중단, 및 방법: 예외 처리를 사용하여 병렬 루프 중단.

Dd984117.collapse_all(ko-kr,VS.110).gif취소 토큰을 사용 하 여 병렬 작업 취소

task, task_group, 및 structured_task_group 취소 취소 토큰을 사용 하 여 클래스를 지원 합니다.PPL의 정의 concurrency::cancellation_token_sourceconcurrency::cancellation_token 이 목적에 대 한 클래스.취소 토큰을 사용 하 여 작업을 취소 하는 경우 런타임은 해당 토큰을 구독 하는 새 작업을 시작 하지 않습니다.이미 활성화 된 작업 취소 토큰을 모니터링 하 고 중지 수 있습니다.

호출 취소를 시작 하는 concurrency::cancellation_token_source::cancel 메서드.취소를 다음과 같은 방법으로 응답 합니다.

  • 에 대 한 task 개체를 사용 하는 concurrency::is_task_cancellation_requestedconcurrency::cancel_current_task 함수.cancel_current_task현재 작업 하 고 해당 값에 따라 연속 문자를 취소합니다.(취소는 취소 되지 않습니다 토큰 작업 또는 해당 연속 된 연결입니다.)

  • 작업 그룹 및 병렬 알고리즘을 사용 하 여 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 함수를 throw 합니다. 명시적으로 현재 루프 또는 함수에서 반환할 필요가 없습니다.

팁

또는 호출할 수 있는 concurrency::interruption_point 대신 작동 is_task_cancellation_requestedcancel_current_task.

호출 하는 것이 중요 cancel_current_task 이 작업 취소 상태로 전환 되므로 취소를 응답 합니다.초기 대신 전화를 반환 하면 cancel_current_task, 작업 상태를 완료로 전환 및 값에 따라 연속 된 실행 됩니다.

주의 정보주의

Throw task_canceled 코드에서.호출 cancel_current_task 대신 합니다.

작업 취소 상태에서 끝날 때의 concurrency::task::get 메서드가 throw concurrency::task_canceled.(반대로 concurrency::task::wait 반환 task_status::canceled 및 throw 하지 않습니다.) 다음 예제에서는이 동작을 대 한 작업 기반 연속 보여 줍니다.작업 기반 연속도 선행 작업이 취소 된 경우 항상 호출 됩니다.

// 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.
*/

명시적 토큰과 함께 만들어진 경우 연속 된 값에 따라 해당 선행 작업의 토큰 상속 하므로 연속도 선행 작업을 계속 실행 되 면 즉시 취소 상태를 입력 합니다.따라서 취소 후 선행 작업에서 throw 된 예외는 연속 작업에 전파 되지 않습니다.취소 항상 선행 작업의 상태를 무시합니다.다음 예제는 이전 비슷하지만의 값에 따라 연속 동작을 보여 줍니다.

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 함수가 해당 작업이 아닌 취소할 수 있습니다.취소 토큰 같은 중첩된 작업 (즉, 다른 작업의 본문에서 만든 작업)의 생성자에 전달 해야 또한 동시에 모든 작업을 취소 합니다.

취소 토큰을 취소 하는 경우 임의의 코드를 실행 하려는 경우도 있습니다.예를 들어, 사용자가 선택 하는 경우는 취소 단추 사용자 인터페이스에서 작업을 취소 하려면 사용자가 다른 작업을 시작할 때까지 해당 단추를 비활성화할 수 있습니다.다음 예제에서는 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.
*/

문서 작업 병렬 처리(동시성 런타임) 값 및 작업 기반 연속 된 차이점에 설명 합니다.제공 하지 않는 경우는 cancellation_token 계속 상속 취소 토큰에서 선행 작업은 다음과 같은 방법으로 연속 작업에 개체:

  • 값에 따라 연속 항상 선행 작업의 취소 토큰을 상속합니다.

  • 작업 기반 연속 절대로 선행 작업의 취소 토큰을 상속합니다.취소할 수 있는 작업 기반 연속 하는 유일한 방법은 명시적으로 취소 토큰을 전달 하는 것.

이러한 현상은 폴트 작업 (즉, 하나는 예외를 throw)가 영향을 받지 않습니다.이 경우 값에 따라 연속 취소 됩니다. 작업 기반 연속 취소 되지 않았습니다.

주의 정보주의

다른 작업 (즉, 중첩 된 작업)에서 만들어지는 작업 부모 작업의 취소 토큰을 상속 하지 않습니다.만 값에 따라 연속 선행 작업 취소 토큰을 상속합니다.

팁

사용은 concurrency::cancellation_token:: 없음 생성자 또는 사용 하는 함수를 호출 하면 메서드는 cancellation_token 개체와 사용 하지 않을 작업을 취소할 수 있습니다.

취소 토큰의 생성자를 제공할 수도 있습니다는 task_group 또는 structured_task_group 개체입니다.중요 한 부분은이 자식 작업 그룹이 취소 토큰을 상속 됩니다.사용 하 여이 개념을 보여 주는 예제는 concurrency::run_with_cancellation_token 함수를 호출 하는 실행 parallel_for, 참조 병렬 알고리즘 취소 이 문서 뒷부분.

Top

Dd984117.collapse_all(ko-kr,VS.110).gif취소 토큰 및 작업 구성

Concurrency::when_allconcurrency::when_any 함수 도움말에서는 일반적인 패턴을 구현 하는 여러 작업을 구성 합니다.취소 토큰으로 이러한 기능을 어떻게 설명 합니다.

취소 토큰은 제공은 when_allwhen_any 함수와 함수 토큰이 취소를 취소 하거나 참가자 중 종료 취소 됨 상태의 작업 또는 예외를 throw 하면 취소 하는.

when_all 함수에서 취소 토큰을 제공 하지 않는 경우에 전체 작업을 작성 하는 각 작업 취소 토큰을 상속 합니다.반환 된 작업 when_all 이러한 토큰을 취소 하는 경우 참가자 작업 중 하나 이상이 아직 시작 되지 않았거나 실행 취소 됩니다.작업 중 하나에서 반환 되는 작업 – 예외를 throw 하는 경우에 이와 유사한 문제 발생 when_all 해당 예외를 즉시 취소 됩니다.

취소 토큰에서 반환 되는 작업에 대 한 런타임을 선택 when_any 해당 작업을 완료 하면 작동 합니다.참가자 작업 완료 상태를 완료 하 고 하나 이상의 작업에서 예외가 throw 되 면 throw 작업 중 하나를 완료 합니다 선택은 when_any 및 토큰은 토큰에 대 한 최종 작업으로 선택 됩니다.둘 이상의 작업에 완료 된 완료 되 면 상태를 반환 하는 작업 when_any 작업이 완료 된 상태에서 끝납니다.런타임에서 해당 토큰입니다 취소 완료 시 작업에는 완료 된 작업을 선택 하려고 반환 된 when_any 을 나중에 실행 중인 다른 작업을 완료할 수 있지만 바로 취소 됩니다.

Top

Dd984117.collapse_all(ko-kr,VS.110).gifcancel 메서드를 사용하여 병렬 작업 취소

Concurrency::task_group::cancelconcurrency::structured_task_group::cancel 작업 그룹이 취소 상태로 설정 됩니다.cancel을 호출한 후에는 작업 그룹에서 이후 작업이 시작되지 않습니다.cancel 메서드는 여러 자식 작업에 의해 호출될 수 있습니다.작업이 취소 된 concurrency::task_group::waitconcurrency::structured_task_group::wait 반환 하는 방법을 concurrency::canceled.

작업 그룹이 취소되는 경우 각 자식 작업에서 런타임을 호출하면 중단 지점이 트리거되어 런타임에서 내부 예외 형식을 throw하고 catch하여 활성 작업을 취소할 수 있습니다.동시성 런타임에서는 특정 중단 지점을 정의하지 않습니다. 런타임에 대한 어떤 호출에서나 중단 지점이 발생할 수 있습니다.런타임에서는 취소를 수행하기 위해 런타임에서 throw하는 예외를 처리해야 합니다.따라서 작업 본문에서 알 수 없는 예외를 처리하지 마십시오.

자식 작업에서 시간이 오래 걸리는 작업을 수행하는 경우 런타임을 호출하지 않으면 주기적으로 취소 여부를 확인하고 적시에 종료해야 합니다.다음 예제에서는 작업 취소 시기를 결정할 수 있는 한 가지 방법을 보여 줍니다.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();

이 예제에서는 해당 작업 루프의 100번째 반복마다 취소 여부를 확인합니다.취소 여부를 확인하는 빈도는 수행하는 작업의 양과 작업이 취소에 응답해야 하는 속도에 따라 달라집니다.

부모 작업 그룹 개체에 액세스할 수 없는 경우 전화를 concurrency::is_current_task_group_canceling 부모 작업 그룹이 취소 여부를 결정 하는 함수입니다.

cancel 메서드는 자식 작업에만 영향을 줍니다.예를 들어 병렬 작업 트리 그림에서 tg1 작업 그룹을 취소하면 트리의 모든 작업(t1, t2, t3, t4t5)에 영향을 줍니다.중첩 작업 그룹인 tg2를 취소할 경우에는 t4t5 작업에만 영향을 줍니다.

cancel 메서드를 호출하면 모든 자식 작업 그룹도 취소됩니다.그러나 병렬 작업 트리에서 해당 작업 그룹의 부모에는 취소가 적용되지 않습니다.다음 예제에서는 병렬 작업 트리 그림에서 빌드하여 이를 보여 줍니다.

첫 번째 예제에서는 tg2 작업 그룹의 자식인 t4 작업에 대한 작업 함수를 만듭니다.이 작업 함수는 루프에서 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, t4t5)에 영향을 줍니다.

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::cancelconcurrency::structured_task_group::is_canceling 메서드.자식 작업 부모 작업 그룹이 취소 하 고 취소를 확인 합니다. 이러한 메서드를 호출할 수 있습니다.

주의 정보주의

자식으로 실행 되는 작업 그룹에서 수행 하는 작업을 취소 하려면 취소 토큰을 사용할 수 있지만 task 개체를 사용할 수 없습니다는 task_group::cancel 또는 structured_task_group::cancel 취소 하는 방법을 task 작업 그룹에서 실행 되는 개체입니다.

Top

Dd984117.collapse_all(ko-kr,VS.110).gif예외를 사용하여 병렬 작업 취소

취소 토큰을 사용 하는 cancel 병렬 작업 트리 취소를 처리 하는 예외를 보다 더 효율적입니다.취소 토큰 및 cancel 하향식 방식으로 작업 및 모든 자식 작업 메서드를 취소 합니다.반대로 예외 처리는 아래에서 위로 동작하며, 예외가 위쪽으로 전파할 때 각 자식 작업 그룹을 독립적으로 취소해야 합니다.동시성 런타임에서 예외 처리 항목에서는 동시성 런타임에서 예외를 사용하여 오류를 전달하는 방법에 대해 설명합니다.그러나 모든 예외가 오류를 나타내는 것은 아닙니다.예를 들어, 결과 찾으면 검색 알고리즘 관련된 작업은 취소 될 수 있습니다.그러나 앞에서 언급한 대로 예외 처리는 병렬 작업을 취소할 때 cancel 메서드를 사용하는 것보다 효율성이 떨어지는 방법입니다.

주의 정보주의

필요할 때만 병렬 작업을 취소 하려면 예외를 사용 하는 것이 좋습니다.취소 토큰 및 작업 그룹 cancel 메서드는 보다 효율적이 고 오류가 발생할 가능성이 적습니다.

작업 그룹에 전달하는 작업 함수의 본문에서 예외를 throw하는 경우 런타임에서는 해당 예외를 저장하고, 작업 그룹이 끝날 때까지 기다리는 컨텍스트로 예외를 마샬링합니다.cancel 메서드와 마찬가지로 런타임에서는 아직 시작되지 않은 작업을 취소하고 새 작업을 수락하지 않습니다.

세 번째 예제는 두 번째 예제와 유사하지만 t4 작업이 예외를 throw하여 tg2 작업 그룹을 취소한다는 점이 다릅니다.이 예제에서는 tg2 작업 그룹에서 자식 작업이 끝날 때까지 기다리는 경우 try-catch 블록을 사용하여 취소를 확인합니다.이렇게 되면 첫 번째 예제와 마찬가지로 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;
}

이 네 번째 예제에서는 예외 처리를 사용하여 전체 작업 트리를 취소합니다.이 예제에서는 tg2 작업 그룹이 자식 작업을 기다리는 경우 대신 tg1 작업 그룹이 자식 작업이 끝날 때까지 기다리는 경우에 예외를 catch합니다.이렇게 되면 두 번째 예제와 마찬가지로 트리에서 tg1tg2 작업 그룹이 둘 다 취소된 상태로 설정됩니다.

// 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::waitstructured_task_group::wait 메서드는 자식 작업이 예외를 throw할 때 throw되므로 두 메서드로부터 반환 값을 받을 수 없습니다.

Top

병렬 알고리즘 취소

병렬 알고리즘에서 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.
   }
});

각 취소 방법은 다른 방법보다 우수한 이점이 있습니다.따라서 특정 요구에 맞는 방법을 선택하십시오.

Top

취소를 사용하지 않는 경우

관련된 작업 그룹의 각 멤버가 적시에 종료할 수 있는 경우 취소를 사용하는 것이 적합합니다.그러나 취소가 응용 프로그램에 적합하지 않는 몇 가지 시나리오가 있습니다.예를 들어 작업 취소는 협력적이므로 개별 작업이 차단되면 전체 작업 집합이 취소되지 않습니다.예를 들어 한 작업이 아직 시작되지 않았는데 다른 활성 작업의 차단을 해제하는 경우 작업 그룹이 취소되면 해당 작업이 시작되지 않습니다.이로 인해 응용 프로그램에서 교착 상태가 발생할 수 있습니다.취소를 사용하는 것이 적합하지 않을 수 있는 경우의 두 번째 예는 작업이 취소되었지만 작업의 자식 작업에서 리소스 해제와 같은 중요한 작업을 수행하는 경우입니다.부모 작업(task)을 취소하면 전체 작업(task) 집합이 취소되므로 해당 작업(operation)은 실행되지 않습니다.이러한 지점을 보여 주는 예제를 보려면 병렬 패턴 라이브러리의 유용한 정보 항목에 있는 Understand how Cancellation and Exception Handling Affect Object Destruction 단원을 참조하십시오.

Top

관련 항목

제목

설명

방법: 취소를 사용하여 병렬 루프 중단

취소를 사용하여 병렬 검색 알고리즘을 구현하는 방법을 보여 줍니다.

방법: 예외 처리를 사용하여 병렬 루프 중단

사용 하는 방법을 보여 줍니다 있는 task_group 클래스는 기본 트리 구조에 대 한 검색 알고리즘을 쓸.

동시성 런타임에서 예외 처리

작업 그룹, 간단한 작업 및 비동기 에이전트에서 throw하는 예외를 런타임에서 처리하는 방법과 응용 프로그램에서 예외에 응답하는 방법을 설명합니다.

작업 병렬 처리(동시성 런타임)

작업이 작업 그룹과 관련되는 방식 및 응용 프로그램에서 구조적 작업과 비구조적 작업을 사용하는 방법에 대해 설명합니다.

병렬 알고리즘

데이터 컬렉션에 대한 작업을 동시에 수행하는 병렬 알고리즘에 대해 설명합니다.

PPL(병렬 패턴 라이브러리)

병렬 패턴 라이브러리에 대한 개요를 제공합니다.

참조

작업 클래스(동시성 런타임)

cancellation_token_source 클래스

cancellation_token 클래스

task_group 클래스

structured_task_group 클래스

parallel_for 함수