Gör så här: Konvertera en OpenMP-loop som använder undantagshantering för att använda Concurrency-ramverket

Det här exemplet visar hur du konverterar en OpenMP-parallellför loop som utför undantagshantering till att använda undantagshanteringsmekanismen i Concurrency Runtime.

I OpenMP måste ett undantag som genereras i en parallell region fångas upp och hanteras i samma region av samma tråd. Ett undantag som undflyr den parallella regionen fångas av den ohanterade undantagshanteraren, vilket avslutar processen som standard.

När du i Concurrency Runtime genererar ett undantag i brödtexten för en arbetsfunktion som du skickar till en aktivitetsgrupp, till exempel en concurrency::task_group eller concurrency::structured_task_group objekt, eller till en parallell algoritm som concurrency::parallel_for, lagrar körningen undantaget och överför det till konteksten som väntar på att aktivitetsgruppen eller algoritmen ska slutföras. För aktivitetsgrupper är den väntande kontexten den kontext som anropar concurrency::task_group::wait, concurrency::structured_task_group::wait, concurrency::task_group::run_and_wait eller concurrency::structured_task_group::run_and_wait. För en parallell algoritm är väntekontexten den kontext som anropade den algoritmen. Körningstiden stoppar även alla aktiva uppgifter som finns i uppgiftsgruppen, inklusive de i underordnade uppgiftsgrupper, och ignorerar alla uppgifter som ännu inte har startats.

Exempel

Det här exemplet visar hur du hanterar undantag i en OpenMP-region parallel och i ett anrop till parallel_for. Funktionen do_work utför en minnesallokeringsbegäran som inte lyckas och genererar därför ett undantag av typen std::bad_alloc. I den version som använder OpenMP måste tråden som genererar undantaget också fånga den. Med andra ord måste varje iteration av en Parallell OpenMP-loop hantera undantaget. I den version som använder Concurrency Runtime fångar huvudtråden ett undantag som genereras av en annan tråd.

// concrt-omp-exceptions.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <new>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// Demonstrates a function that performs a memory allocation request 
// that does not succeed.
void do_work(int)
{
   // The following memory allocation causes this function to 
   // throw std::bad_alloc.
   char* ptr = new char[(~unsigned int((int)0)/2) - 1];

   // TODO: Assuming that the allocation succeeds, perform some work 
   // and free the allocated memory.

   delete[] ptr;
}

// Demonstrates an OpenMP parallel loop that performs exception handling.
void omp_exception_handling()
{
   #pragma omp parallel for 
      for(int i = 0; i < 10; i++) 
      {
         try {
            // Perform a unit of work.
            do_work(i);
         }
         catch (exception const& e) {
            // Print the error to the console.
            wstringstream ss;
            ss << L"An error of type '" << typeid(e).name() 
               << L"' occurred." << endl;
            wcout << ss.str();
         }
      }
}

// Demonstrates an Concurrency Runtime parallel loop that performs exception handling.
void concrt_exception_handling()
{
   try {
      parallel_for(0, 10, [](int i) 
      {
         // Perform a unit of work.
         do_work(i);
      });
   }
   catch (exception const& e) {
      // Print the error to the console.
      wcout << L"An error of type '" << typeid(e).name() 
            << L"' occurred." << endl;
   }
}

int wmain()
{
   wcout << L"Using OpenMP..." << endl;
   omp_exception_handling();

   wcout << L"Using the Concurrency Runtime..." << endl;
   concrt_exception_handling();
}

Det här exemplet genererar följande utdata.

Using OpenMP...
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
Using the Concurrency Runtime...
An error of type 'class std::bad_alloc' occurred.

I den version av det här exemplet som använder OpenMP sker undantaget i och hanteras av varje loop-iteration. I den version som använder Concurrency Runtime lagrar körningen undantaget, stoppar alla aktiva aktiviteter, tar bort alla aktiviteter som ännu inte har startats och konverterar undantaget till kontexten som anropar parallel_for.

Om du kräver att den version som använder OpenMP avslutas när undantaget inträffar kan du använda en boolesk flagga för att signalera till andra loop-iterationer om att felet inträffade. Som i exemplet i avsnittet How to: Convert an OpenMP Loop that Uses Cancellation to Use the Concurrency Runtime (Konvertera en OpenMP-loop som använder Annullering för att använda samtidighetskörning) skulle efterföljande loop-iterationer inte göra någonting om flaggan har angetts. Om du däremot kräver att loopen som använder Concurrency Runtime fortsätter efter att undantaget inträffar hanterar du undantaget i själva den parallella loopkroppen.

Andra komponenter i Concurrency Runtime, till exempel asynkrona agenter och lätta uppgifter, transporterar inte undantag. I stället fångas ohanterade undantag av den ohanterade undantagshanteraren, vilket som standard avslutar processen. Mer information om undantagshantering finns i Undantagshantering.

Mer information om parallel_for och andra parallella algoritmer finns i Parallella algoritmer.

Kompilera koden

Kopiera exempelkoden och klistra in den i ett Visual Studio-projekt, eller klistra in den i en fil med namnet concrt-omp-exceptions.cpp och kör sedan följande kommando i ett Visual Studio-kommandotolkfönster.

cl.exe /EHsc /openmp concrt-omp-exceptions.cpp

Se även

Migrera från OpenMP till Concurrency Runtime
undantagshantering
Parallella algoritmer