Udostępnij za pośrednictwem


Obsługa wyjątków we współbieżności środowiska wykonawczego

Środowisko uruchomieniowe współbieżności używa obsługi wyjątków języka C++, aby komunikować się z wieloma rodzajami błędów. Te błędy obejmują nieprawidłowe użycie środowiska uruchomieniowego, błędy środowiska uruchomieniowego, takie jak niepowodzenie uzyskania zasobu, oraz błędy występujące w funkcjach roboczych, które są zapewniane dla zadań i grup zadań. Gdy zadanie lub grupa zadań zgłasza wyjątek, środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który czeka na zakończenie zadania lub grupy zadań. W przypadku składników, takich jak uproszczone zadania i agenci, środowisko uruchomieniowe nie zarządza wyjątkami. W takich przypadkach należy zaimplementować własny mechanizm obsługi wyjątków. W tym temacie opisano sposób obsługi wyjątków zgłaszanych przez zadania, grupy zadań, uproszczone zadania i agentów asynchronicznych oraz sposób reagowania na wyjątki w aplikacjach.

Kwestie kluczowe

  • Gdy zadanie lub grupa zadań zgłasza wyjątek, środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który czeka na zakończenie zadania lub grupy zadań.

  • Jeśli to możliwe, otaczaj każde wywołanie współbieżności::task::get i współbieżności::task::wait z blokiem try/catch w celu obsługi błędów, z których można odzyskać. Środowisko uruchomieniowe kończy działanie aplikacji, jeśli zadanie zgłasza wyjątek i że wyjątek nie jest przechwytywane przez zadanie, jedną z jego kontynuacji lub główną aplikację.

  • Kontynuacja oparta na zadaniach zawsze jest uruchamiana; nie ma znaczenia, czy zadanie antecedent zostało ukończone pomyślnie, rzuciło wyjątek, czy zostało anulowane. Kontynuacja oparta na wartości nie jest uruchamiana, jeśli zadanie antecedent zgłasza lub anuluje.

  • Ponieważ kontynuacje oparte na zadaniach są zawsze uruchamiane, rozważ dodanie kontynuacji opartej na zadaniach na końcu łańcucha kontynuacji. Może to pomóc zagwarantować, że kod będzie obserwować wszystkie wyjątki.

  • Środowisko uruchomieniowe zgłasza współbieżność::task_canceled po wywołaniu współbieżności::task::get i anulowaniu tego zadania.

  • Środowisko uruchomieniowe nie zarządza wyjątkami dla lekkich zadań i agentów.

W tym dokumencie

Zadania i kontynuacje

W tej sekcji opisano sposób obsługi wyjątków zgłaszanych przez obiekty concurrency::task i ich kontynuacje. Aby uzyskać więcej informacji na temat modelu zadania i kontynuacji, zobacz Równoległość zadań.

Po wystąpieniu wyjątku w treści funkcji pracy przekazanej do task obiektu środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który wywołuje współbieżność::task::get lub współbieżność::task::task::wait. Dokument Równoległość zadań opisuje kontynuacje oparte na zadaniach i oparte na wartości, ale podsumowując, kontynuacja oparta na wartości przyjmuje parametr typuT, a kontynuacja oparta na zadaniach przyjmuje parametr typu task<T>. Jeśli zadanie, które zgłasza, ma co najmniej jedną kontynuację opartą na wartości, te kontynuacje nie są zaplanowane do uruchomienia. Poniższy przykład ilustruje to zachowanie:

// eh-task.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    wcout << L"Running a task..." << endl;
    // Create a task that throws.
    auto t = create_task([]
    {
        throw exception();
    });
    
    // Create a continuation that prints its input value.
    auto continuation = t.then([]
    {
        // We do not expect this task to run because
        // the antecedent task threw.
        wcout << L"In continuation task..." << endl;
    });

    // Wait for the continuation to finish and handle any 
    // error that occurs.
    try
    {
        wcout << L"Waiting for tasks to finish..." << endl;
        continuation.wait();

        // Alternatively, call get() to produce the same result.
        //continuation.get();
    }
    catch (const exception& e)
    {
        wcout << L"Caught exception." << endl;
    }
}
/* Output:
    Running a task...
    Waiting for tasks to finish...
    Caught exception.
*/

Kontynuacja oparta na zadaniach umożliwia obsługę wszelkich wyjątków zgłaszanych przez zadanie przedzibowe. Kontynuacja oparta na zadaniach zawsze jest uruchamiana; nie ma znaczenia, czy zadanie zostało ukończone pomyślnie, zgłosiło wyjątek, czy zostało anulowane. Gdy zadanie zgłasza wyjątek, jego kontynuacje oparte na zadaniach są zaplanowane do uruchomienia. W poniższym przykładzie pokazano zadanie, które zawsze zgłasza. Zadanie ma dwie kontynuacje; jeden jest oparty na wartości, a drugi jest oparty na zadaniach. Wyjątek oparty na zadaniach zawsze jest uruchamiany i dlatego może przechwytywać wyjątek zgłaszany przez zadanie antecedent. Gdy w przykładzie zaczeka na zakończenie obu kontynuacji, wyjątek jest zgłaszany ponownie, ponieważ wyjątek zadania jest zawsze zgłaszany w task::get momencie wywołania lub task::wait wywołania.

// eh-continuations.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{    
    wcout << L"Running a task..." << endl;
    // Create a task that throws.
    auto t = create_task([]() -> int
    {
        throw exception();
        return 42;
    });

    //
    // Attach two continuations to the task. The first continuation is  
    // value-based; the second is task-based.

    // Value-based continuation.
    auto c1 = t.then([](int n)
    {
        // We don't expect to get here because the antecedent 
        // task always throws.
        wcout << L"Received " << n << L'.' << endl;
    });

    // Task-based continuation.
    auto c2 = t.then([](task<int> previousTask)
    {
        // We do expect to get here because task-based continuations
        // are scheduled even when the antecedent task throws.
        try
        {
            wcout << L"Received " << previousTask.get() << L'.' << endl;
        }
        catch (const exception& e)
        {
            wcout << L"Caught exception from previous task." << endl;
        }
    });

    // Wait for the continuations to finish.
    try
    {
        wcout << L"Waiting for tasks to finish..." << endl;
        (c1 && c2).wait();
    }
    catch (const exception& e)
    {
        wcout << L"Caught exception while waiting for all tasks to finish." << endl;
    }
}
/* Output:
    Running a task...
    Waiting for tasks to finish...
    Caught exception from previous task.
    Caught exception while waiting for all tasks to finish.
*/

Zalecamy używanie kontynuacji opartych na zadaniach w celu przechwytywania wyjątków, które można obsłużyć. Ponieważ kontynuacje oparte na zadaniach są zawsze uruchamiane, rozważ dodanie kontynuacji opartej na zadaniach na końcu łańcucha kontynuacji. Może to pomóc zagwarantować, że kod będzie obserwować wszystkie wyjątki. W poniższym przykładzie przedstawiono podstawowy łańcuch kontynuacji oparty na wartości. Trzecie zadanie w łańcuchu zgłasza i w związku z tym wszelkie kontynuacje oparte na wartości, które następują po nim, nie są uruchamiane. Ostatnia kontynuacja jest jednak oparta na zadaniach i dlatego zawsze jest uruchamiana. Ta ostatnia kontynuacja obsługuje wyjątek zgłaszany przez trzecie zadanie.

Zalecamy przechwycenie najbardziej specyficznych wyjątków, które można wykonać. Możesz pominąć tę ostateczną kontynuację opartą na zadaniach, jeśli nie masz określonych wyjątków do przechwycenia. Każdy wyjątek pozostanie nieobsługiwany i może zakończyć działanie aplikacji.

// eh-task-chain.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
    int n = 1;
    create_task([n]
    {
        wcout << L"In first task. n = ";
        wcout << n << endl;
        
        return n * 2;

    }).then([](int n)
    {
        wcout << L"In second task. n = ";
        wcout << n << endl;

        return n * 2;

    }).then([](int n)
    {
        wcout << L"In third task. n = ";
        wcout << n << endl;

        // This task throws.
        throw exception();
        // Not reached.
        return n * 2;

    }).then([](int n)
    {
        // This continuation is not run because the previous task throws.
        wcout << L"In fourth task. n = ";
        wcout << n << endl;

        return n * 2;

    }).then([](task<int> previousTask)
    {
        // This continuation is run because it is task-based.
        try
        {
            // The call to task::get rethrows the exception.
            wcout << L"In final task. result = ";
            wcout << previousTask.get() << endl;
        }
        catch (const exception&)
        {
            wcout << L"<exception>" << endl;
        }
    }).wait();
}
/* Output:
    In first task. n = 1
    In second task. n = 2
    In third task. n = 4
    In final task. result = <exception>
*/

Napiwek

Możesz użyć metody concurrency::task_completion_event::set_exception , aby skojarzyć wyjątek ze zdarzeniem ukończenia zadania. W dokumencie Równoległość zadań opisano bardziej szczegółowo klasę concurrency::task_completion_event .

concurrency::task_canceled jest ważnym typem wyjątku środowiska uruchomieniowego, który odnosi się do taskelementu . Środowisko uruchomieniowe jest zgłaszane task_canceled po wywołaniu task::get i anulowaniu tego zadania. (Z drugiej strony zwraca task::waitwartość task_status::canceled i nie zgłasza). Ten wyjątek można przechwycić i obsłużyć z kontynuacji opartej na zadaniach lub wywołania metody task::get. Aby uzyskać więcej informacji na temat anulowania zadania, zobacz Anulowanie w PPL.

Uwaga

Nigdy nie zgłaszaj task_canceled kodu. Wywołaj współbieżność::cancel_current_task zamiast tego.

Środowisko uruchomieniowe kończy działanie aplikacji, jeśli zadanie zgłasza wyjątek i że wyjątek nie jest przechwytywane przez zadanie, jedną z jego kontynuacji lub główną aplikację. Jeśli aplikacja ulegnie awarii, możesz skonfigurować program Visual Studio tak, aby przerywał zgłaszanie wyjątków języka C++. Po zdiagnozowaniu lokalizacji nieobsługiwanego wyjątku użyj kontynuacji opartej na zadaniach, aby go obsłużyć.

W sekcji Wyjątki zgłaszane przez środowisko uruchomieniowe w tym dokumencie opisano sposób pracy z wyjątkami środowiska uruchomieniowego bardziej szczegółowo.

[Top]

Grupy zadań i algorytmy równoległe

W tej sekcji opisano sposób obsługi wyjątków zgłaszanych przez grupy zadań przez środowisko uruchomieniowe. Ta sekcja dotyczy również algorytmów równoległych, takich jak concurrency::p arallel_for, ponieważ te algorytmy są oparte na grupach zadań.

Uwaga

Upewnij się, że rozumiesz wpływ wyjątków na zadania zależne. Aby zapoznać się z zalecanymi rozwiązaniami dotyczącymi używania obsługi wyjątków z zadaniami lub algorytmami równoległymi, zobacz sekcję Opis sposobu anulowania i obsługi wyjątków wpływania na niszczenie obiektów w temacie Best Practices in the Parallel Patterns Library (Opis sposobu anulowania i obsługi wyjątków) w temacie Best Practices in the Parallel Patterns Library (Najlepsze rozwiązania w bibliotece wzorców równoległych).

Aby uzyskać więcej informacji na temat grup zadań, zobacz Równoległość zadań. Aby uzyskać więcej informacji na temat algorytmów równoległych, zobacz Parallel Algorithms (Algorytmy równoległe).

Po wystąpieniu wyjątku w treści funkcji pracy przekazywanej do współbieżności::task_group lub współbieżności::structured_task_group obiektu środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu wywołującego współbieżność::task_group::wait, concurrency::structured_task_group::wait, concurrency::wait, concurrency::task_group::run_and_wait lub concurrency:: structured_task_group::run_and_wait. Środowisko uruchomieniowe zatrzymuje również wszystkie aktywne zadania, które znajdują się w grupie zadań (w tym w podrzędnych grupach zadań) i odrzuca wszystkie zadania, które nie zostały jeszcze uruchomione.

W poniższym przykładzie przedstawiono podstawową strukturę funkcji pracy, która zgłasza wyjątek. W przykładzie użyto task_group obiektu do wydrukowania wartości dwóch point obiektów równolegle. Funkcja robocza print_point wyświetla wartości point obiektu w konsoli programu . Funkcja pracy zgłasza wyjątek, jeśli wartość wejściowa to NULL. Środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który wywołuje metodę task_group::wait.

// eh-task-group.cpp
// compile with: /EHsc
#include <ppl.h>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// Defines a basic point with X and Y coordinates.
struct point
{
   int X;
   int Y;
};

// Prints the provided point object to the console.
void print_point(point* pt)
{
   // Throw an exception if the value is NULL.
   if (pt == NULL)
   {
      throw exception("point is NULL.");
   }

   // Otherwise, print the values of the point.
   wstringstream ss;
   ss << L"X = " << pt->X << L", Y = " << pt->Y << endl;
   wcout << ss.str();
}

int wmain()
{
   // Create a few point objects.
   point pt = {15, 30};
   point* pt1 = &pt;
   point* pt2 = NULL;

   // Use a task group to print the values of the points.
   task_group tasks;

   tasks.run([&] {
      print_point(pt1);
   });

   tasks.run([&] {
      print_point(pt2);
   });

   // Wait for the tasks to finish. If any task throws an exception,
   // the runtime marshals it to the call to wait.
   try
   {
      tasks.wait();
   }
   catch (const exception& e)
   {
      wcerr << L"Caught exception: " << e.what() << endl;
   }
}

W tym przykładzie są generowane następujące dane wyjściowe.

X = 15, Y = 30Caught exception: point is NULL.

Pełny przykład korzystający z obsługi wyjątków w grupie zadań można znaleźć w temacie How to: Use Exception Handling to Break from a Parallel Loop (Instrukcje: używanie obsługi wyjątków w celu przerwania pętli równoległej).

[Top]

Wyjątki zgłaszane przez środowisko uruchomieniowe

Wyjątek może wynikać z wywołania do środowiska uruchomieniowego. Większość typów wyjątków, z wyjątkiem współbieżności::task_canceled i współbieżności::operation_timed_out, wskazuje błąd programowania. Te błędy są zwykle nieodwracalne i dlatego nie powinny być przechwytywane ani obsługiwane przez kod aplikacji. Sugerujemy, aby przechwytywać lub obsługiwać tylko nieodwracalne błędy w kodzie aplikacji, gdy trzeba zdiagnozować błędy programowania. Jednak zrozumienie typów wyjątków zdefiniowanych przez środowisko uruchomieniowe może pomóc zdiagnozować błędy programowania.

Mechanizm obsługi wyjątków jest taki sam w przypadku wyjątków zgłaszanych przez środowisko uruchomieniowe jako wyjątki zgłaszane przez funkcje pracy. Na przykład funkcja concurrency::receive zgłasza komunikat operation_timed_out , gdy nie otrzymuje komunikatu w określonym przedziale czasu. Jeśli receive zgłasza wyjątek w funkcji roboczej przekazanej do grupy zadań, środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który wywołuje task_group::wait, , structured_task_group::waitlub task_group::run_and_waitstructured_task_group::run_and_wait.

W poniższym przykładzie użyto algorytmu concurrency::p arallel_invoke w celu równoległego uruchamiania dwóch zadań. Pierwsze zadanie czeka pięć sekund, a następnie wysyła komunikat do buforu komunikatów. Drugie zadanie używa receive funkcji , aby odczekać trzy sekundy, aby odebrać komunikat z tego samego buforu komunikatów. Funkcja receive zgłasza komunikat operation_timed_out , jeśli nie otrzyma komunikatu w przedziale czasu.

// eh-time-out.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   single_assignment<int> buffer;
   int result;

   try
   {
      // Run two tasks in parallel.
      parallel_invoke(
         // This task waits 5 seconds and then sends a message to 
         // the message buffer.
         [&] {
            wait(5000); 
            send(buffer, 42);
         },
         // This task waits 3 seconds to receive a message.
         // The receive function throws operation_timed_out if it does 
         // not receive a message in the specified time period.
         [&] {
            result = receive(buffer, 3000);
         }
      );

      // Print the result.
      wcout << L"The result is " << result << endl;
   }
   catch (operation_timed_out&)
   {
      wcout << L"The operation timed out." << endl;
   }
}

W tym przykładzie są generowane następujące dane wyjściowe.

The operation timed out.

Aby zapobiec nietypowemu zakończeniu działania aplikacji, upewnij się, że kod obsługuje wyjątki podczas wywoływania do środowiska uruchomieniowego. Obsługują również wyjątki podczas wywoływania kodu zewnętrznego, który używa środowiska uruchomieniowego współbieżności, na przykład biblioteki innej firmy.

[Top]

Wiele wyjątków

Jeśli zadanie lub algorytm równoległy odbiera wiele wyjątków, środowisko uruchomieniowe marshaluje tylko jeden z tych wyjątków do kontekstu wywołującego. Środowisko uruchomieniowe nie gwarantuje, który wyjątek marshaluje.

W poniższym przykładzie użyto algorytmu parallel_for do drukowania liczb w konsoli programu . Zgłasza wyjątek, jeśli wartość wejściowa jest mniejsza niż wartość minimalna lub większa niż maksymalna. W tym przykładzie wiele funkcji roboczych może zgłosić wyjątek.

// eh-multiple.cpp
// compile with: /EHsc
#include <ppl.h>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

int wmain()
{
   const int min = 0;
   const int max = 10;
   
   // Print values in a parallel_for loop. Use a try-catch block to 
   // handle any exceptions that occur in the loop.
   try
   {
      parallel_for(-5, 20, [min,max](int i)
      {
         // Throw an exeception if the input value is less than the 
         // minimum or greater than the maximum.

         // Otherwise, print the value to the console.

         if (i < min)
         {
            stringstream ss;
            ss << i << ": the value is less than the minimum.";
            throw exception(ss.str().c_str());
         }
         else if (i > max)
         {
            stringstream ss;
            ss << i << ": the value is greater than than the maximum.";
            throw exception(ss.str().c_str());
         }
         else
         {
            wstringstream ss;
            ss << i << endl;
            wcout << ss.str();
         }
      });
   }
   catch (exception& e)
   {
      // Print the error to the console.
      wcerr << L"Caught exception: " << e.what() << endl;
   }  
}

Poniżej przedstawiono przykładowe dane wyjściowe dla tego przykładu.

8293104567Caught exception: -5: the value is less than the minimum.

[Top]

Anulowanie

Nie wszystkie wyjątki wskazują błąd. Na przykład algorytm wyszukiwania może użyć obsługi wyjątków, aby zatrzymać skojarzone zadanie po znalezieniu wyniku. Aby uzyskać więcej informacji na temat używania mechanizmów anulowania w kodzie, zobacz Anulowanie w PPL.

[Top]

Zadania lekkie

Uproszczone zadanie to zadanie zaplanowane bezpośrednio z obiektu concurrency::Scheduler . Uproszczone zadania mają mniejsze obciążenie niż zwykłe zadania. Jednak środowisko uruchomieniowe nie przechwytuje wyjątków zgłaszanych przez uproszczone zadania. Zamiast tego wyjątek jest przechwytywany przez nieobsługiwaną procedurę obsługi wyjątków, która domyślnie kończy proces. W związku z tym należy użyć odpowiedniego mechanizmu obsługi błędów w aplikacji. Aby uzyskać więcej informacji na temat lekkich zadań, zobacz Harmonogram zadań.

[Top]

Agenci asynchroniczni

Podobnie jak uproszczone zadania, środowisko uruchomieniowe nie zarządza wyjątkami zgłaszanymi przez agentów asynchronicznych.

Poniższy przykład przedstawia jeden ze sposobów obsługi wyjątków w klasie pochodzącej z współbieżności::agenta. W tym przykładzie zdefiniowano klasę points_agent . Metoda points_agent::run odczytuje point obiekty z buforu komunikatów i drukuje je w konsoli. Metoda run zgłasza wyjątek, jeśli otrzymuje NULL wskaźnik.

Metoda run otacza całą pracę w try-catch bloku. Blok catch przechowuje wyjątek w buforze komunikatów. Aplikacja sprawdza, czy agent napotkał błąd, odczytując z tego buforu po zakończeniu pracy agenta.

// eh-agents.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Defines a point with x and y coordinates.
struct point
{
   int X;
   int Y;
};

// Informs the agent to end processing.
point sentinel = {0,0};

// An agent that prints point objects to the console.
class point_agent : public agent
{
public:
   explicit point_agent(unbounded_buffer<point*>& points)
      : _points(points)
   { 
   }

   // Retrieves any exception that occurred in the agent.
   bool get_error(exception& e)
   {
      return try_receive(_error, e);
   }

protected:
   // Performs the work of the agent.
   void run()
   {
      // Perform processing in a try block.
      try
      {
         // Read from the buffer until we reach the sentinel value.
         while (true)
         {
            // Read a value from the message buffer.
            point* r = receive(_points);

            // In this example, it is an error to receive a 
            // NULL point pointer. In this case, throw an exception.
            if (r == NULL)
            {
               throw exception("point must not be NULL");
            }
            // Break from the loop if we receive the 
            // sentinel value.
            else if (r == &sentinel)
            {
               break;
            }
            // Otherwise, do something with the point.
            else
            {
               // Print the point to the console.
               wcout << L"X: " << r->X << L" Y: " << r->Y << endl;
            }
         }
      }
      // Store the error in the message buffer.
      catch (exception& e)
      {
         send(_error, e);
      }

      // Set the agent status to done.
      done();
   }

private:
   // A message buffer that receives point objects.
   unbounded_buffer<point*>& _points;

   // A message buffer that stores error information.
   single_assignment<exception> _error;
};

int wmain()
{  
   // Create a message buffer so that we can communicate with
   // the agent.
   unbounded_buffer<point*> buffer;

   // Create and start a point_agent object.
   point_agent a(buffer);
   a.start();

   // Send several points to the agent.
   point r1 = {10, 20};
   point r2 = {20, 30};
   point r3 = {30, 40};

   send(buffer, &r1);
   send(buffer, &r2);
   // To illustrate exception handling, send the NULL pointer to the agent.
   send(buffer, reinterpret_cast<point*>(NULL));
   send(buffer, &r3);
   send(buffer, &sentinel);

   // Wait for the agent to finish.
   agent::wait(&a);
  
   // Check whether the agent encountered an error.
   exception e;
   if (a.get_error(e))
   {
      cout << "error occurred in agent: " << e.what() << endl;
   }
   
   // Print out agent status.
   wcout << L"the status of the agent is: ";
   switch (a.status())
   {
   case agent_created:
      wcout << L"created";
      break;
   case agent_runnable:
      wcout << L"runnable";
      break;
   case agent_started:
      wcout << L"started";
      break;
   case agent_done:
      wcout << L"done";
      break;
   case agent_canceled:
      wcout << L"canceled";
      break;
   default:
      wcout << L"unknown";
      break;
   }
   wcout << endl;
}

W tym przykładzie są generowane następujące dane wyjściowe.

X: 10 Y: 20
X: 20 Y: 30
error occurred in agent: point must not be NULL
the status of the agent is: done

trycatch-Ponieważ blok istnieje poza pętląwhile, agent kończy przetwarzanie, gdy napotka pierwszy błąd. trycatch-Jeśli blok znajdował się wewnątrz pętli, agent będzie kontynuowany po wystąpieniu while błędu.

W tym przykładzie są przechowywane wyjątki w buforze komunikatów, dzięki czemu inny składnik może monitorować agenta pod kątem błędów podczas jego uruchamiania. W tym przykładzie użyto obiektu concurrency::single_assignment do przechowywania błędu. W przypadku, gdy agent obsługuje wiele wyjątków, single_assignment klasa przechowuje tylko pierwszy komunikat, który jest do niego przekazywany. Aby przechowywać tylko ostatni wyjątek, użyj klasy concurrency::overwrite_buffer . Aby przechowywać wszystkie wyjątki, użyj klasy concurrency::unbounded_buffer . Aby uzyskać więcej informacji na temat tych bloków komunikatów, zobacz Asynchroniczne bloki komunikatów.

Aby uzyskać więcej informacji na temat agentów asynchronicznych, zobacz Asynchronous Agents (Agenci asynchroniczne).

[Top]

Podsumowanie

[Top]

Zobacz też

Środowisko uruchomieniowe współbieżności
Równoległość zadań
Algorytmy równoległe
Anulowanie w PPL
Harmonogram zadań
Agenci asynchroniczni