Aracılığıyla paylaş


Özel durum işleme eşzamanlılık çalışma zamanında

Eşzamanlılık çalışma zamanı c++ özel durum işleme hataları birçok türde iletişim kurmak için kullanır.Bu hatalar ortaya çıkan hataların çalışma zamanı ve çalışma zamanı hataları bir kaynağını alma hatası gibi geçersiz kullanımı iş görevleri ve Görev grupları sağlayan işlevler ekleyin.Görev veya görev grubu bir istisna atar, çalışma zamanı bu özel durumu tutan ve görev veya bitirmek için görev grubu için bekler bağlamına sýralar.Basit görevleri ve aracıları gibi bileşenler için özel durumlar için çalışma zamanı yönetmez.Bu gibi durumlarda, kendi özel durum işleme mekanizmasına uygulamalısınız.Bu konuda çalışma zamanı görevler, Görev grupları, basit görevleri ve zaman uyumsuz aracıları tarafından atılan özel durum işleme biçimini ve özel durumlar uygulamalarınızda isteklerine nasıl açıklar.

Önemli noktalar

  • Görev veya görev grubu bir istisna atar, çalışma zamanı bu özel durumu tutan ve görev veya bitirmek için görev grubu için bekler bağlamına sýralar.

  • Mümkün olduğunda, her çağrının saran concurrency::task::get ve concurrency::task::wait ile bir try/catch kurtarıp kurtaramadığını hataları işlemek için blok.Bir görevi bir istisna atar ve göreve göre bir kendi continuations ya da ana uygulama özel durum yakalandı değil çalışma zamanı uygulaması sonlandırır.

  • Bir görev tabanlı devamı her zaman çalışır; Öncül görev başarıyla tamamlandı, bir özel durum oluşturdu veya iptal edildi mi önemli değildir.Öncül görev oluşturduğunda veya iptal eder, değerine göre devamı çalışmaz.

  • Görev tabanlı continuations her zaman çalıştığından, görev tabanlı devamı devamı zincirinin sonunda eklenip eklenmeyeceğini göz önünde bulundurun.Bu, kodunuzun tüm özel durumları gözlemliyorsa garanti yardımcı olabilir.

  • Çalışma zamanı atan concurrency::task_canceled aradığınızda concurrency::task::get ve söz konusu işi iptal edildi.

  • Çalışma zamanında basit görevleri ve aracıları için özel durumlar yönetmez.

Bu belgede yer alan

  • Görevleri ve Continuations

  • Görev grupları ve paralel algoritmalar

  • Çalışma zamanı tarafından oluşturulan özel durum

  • Birden çok özel durumlar

  • İptal etme

  • Basit görevleri

  • Zaman uyumsuz aracıları

Görevleri ve Continuations

Bu bölüm, çalışma zamanı tarafından atılan istisnalar nasıl işlediğini açıklar concurrency::task nesneleri ve bunların continuations.Görev ve devamı modeli hakkında daha fazla bilgi için bkz: Görev paralellik (eşzamanlılık çalışma zamanı).

Bir özel durum geçişi için bir iş işlev gövdesinde throw ne zaman bir task nesne, çalışma zamanı, özel duruma saklar ve çağıran bağlamına sýralar concurrency::task::get veya concurrency::task::wait.Belge Görev paralellik (eşzamanlılık çalışma zamanı) açıklar değerine göre devamı türünde bir parametre alır görev tabanlı özetlemek üzere ama değerine göre continuations karşı T ve görev tabanlı devamı türünde bir parametre alır task<T>.Bir veya daha fazla değere göre continuations atan bir görev varsa, bu continuations çalıştırılacak zamanlanmış değil.Bu davranış aşağıdaki örnekte gösterilmiştir:

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

Görev tabanlı devamı, öncül görev tarafından atılan herhangi bir özel durum işleme olanak tanır.Bir görev tabanlı devamı her zaman çalışır; Görev başarıyla tamamlandı, bir özel durum oluşturdu veya iptal edildi mi önemli değildir.Bir görevi bir istisna atar, kendi görev tabanlı continuations çalışacak şekilde zamanlanır.Aşağıdaki örnek, her zaman atan bir görev gösterir.Görev iki continuations sahiptir; bir değeri temel alan ve diğer görev tabanlı.Görev tabanlı özel durum her zaman çalışır ve bu nedenle öncül görev tarafından atılan özel durum yakalayabilirsiniz.Örnek hem continuations bitmesini bekler, görev durumu her zaman ne zaman atılır çünkü istisnası yeniden atılır task::get veya task::wait olarak adlandırılır.

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

Görev tabanlı continuations işleyebilen özel durumları yakalamak için kullanmanızı öneririz.Görev tabanlı continuations her zaman çalıştığından, görev tabanlı devamı devamı zincirinin sonunda eklenip eklenmeyeceğini göz önünde bulundurun.Bu, kodunuzun tüm özel durumları gözlemliyorsa garanti yardımcı olabilir.Aşağıdaki örnek, temel değerine göre devamı zincir gösterir.Üçüncü görev zincirindeki atan ve onu izleyen herhangi bir değere göre continuations değil bu nedenle çalıştırılır.Ancak, nihai devamı görev tabanlı ve bu nedenle her zaman çalışır.Bu son devamı üçüncü görev tarafından atılan özel durum işleme.

Sizin için en özel durum catch öneririz.Yakalamak için özel bir durum yoksa, bu son görev tabanlı devamı atlayabilirsiniz.Herhangi bir istisna işlenmeyen kalır ve uygulama işten çıkarabilirsiniz.

// 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 value-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>
*/
İpucuİpucu

Kullanabileceğiniz concurrency::task_completion_event::set_exception bir özel bir görevi tamamlama olayıyla yöntemi.Belge Görev paralellik (eşzamanlılık çalışma zamanı) açıklar concurrency::task_completion_event daha ayrıntılı sınıfı.

CONCURRENCY::task_canceled ilgili önemli çalışma zamanı özel durum türü olan task.Çalışma zamanı atan task_canceled aradığınızda task::get ve söz konusu işi iptal edildi.(Bunun tersi olarak, task::wait döndüren task_status::canceled ve oluşturması değildir.) Catch ve görev tabanlı devamı veya aradığınızda, bu özel durum işleme task::get.Görev iptal etme hakkında daha fazla bilgi için bkz: ppl iptali.

Uyarı notuUyarı

Hiçbir zaman throw task_canceled kodunuzu karşı.Call concurrency::cancel_current_task onun yerine.

Bir görevi bir istisna atar ve göreve göre bir kendi continuations ya da ana uygulama özel durum yakalandı değil çalışma zamanı uygulaması sonlandırır.Uygulamanızın çökerse, Visual Studio c++ özel durumlar atılan çıkarken yapılandırabilirsiniz.İşlenmeyen özel durum konumunu tanılamak sonra görev tabanlı devamı işlenmesi için kullanın.

Bölüm Çalışma zamanı tarafından özel durum oluşturuldu bu belgede daha ayrıntılı çalışma zamanı istisnaları çalışmak açıklar.

Top

Görev grupları ve paralel algoritmalar

Bu bölümde, çalışma zamanı Görev grupları tarafından atılan özel durum işleme biçimini açıklar.Bu bölüm ayrıca paralel algoritmalar gibi geçerlidir concurrency::parallel_for, bu algoritmaların görev gruplarını oluşturun.

Uyarı notuUyarı

Bağımlı görevler üzerinde özel durumlara sahip etkilerini anladığınızdan emin olun.Özel durum işleme görevleri veya paralel algoritmalar ile kullanma hakkında önerilen yöntemler için bkz: Understand how Cancellation and Exception Handling Affect Object Destruction paralel Desenler kitaplığının konusundaki en iyi yöntemler bölümündeki.

Görev grupları hakkında daha fazla bilgi için bkz: Görev paralellik (eşzamanlılık çalışma zamanı).Paralel algoritmalar hakkında daha fazla bilgi için bkz: Paralel algoritmalar.

Bir özel durum geçişi için bir iş işlev gövdesinde throw ne zaman bir concurrency::task_group veya concurrency::structured_task_group nesne, çalışma zamanı, özel duruma saklar ve çağıran bağlamına sýralar concurrency::task_group::wait, concurrency::structured_task_group::wait, concurrency::task_group::run_and_wait, veya concurrency::structured_task_group::run_and_wait.Çalışma zamanı da görev grubu (alt görev gruplarını dahil) olan tüm etkin görevleri durduruyor ve henüz başlatılmamış herhangi bir görevi atar.

Aşağıdaki örnek, bir istisna atar iş işlevi temel yapısını gösterir.Örnek bir task_group iki değerlerini yazdırmak için nesne point paralel nesneleri.print_point İş işlevi değerleri yazdırır bir point Konsolu nesnesi.Girdi değeri ise, iş işlevi bir istisna atar NULL.Çalışma zamanı bu özel depolar ve çağıran bağlamına sýralar 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;
   }
}

Bu örnek aşağıdaki çıktıyı üretir.

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

Özel durum işlemenin bir görev grubu kullanan tam bir örnek için bkz: Nasıl yapılır: özel durum için sonu paralel bir döngü işleme kullanın.

Top

Çalışma zamanı tarafından oluşturulan özel durum

Bir özel çalışma zamanı çağrısına neden olabilir.Çoğu özel durum türü dışında concurrency::task_canceled ve concurrency::operation_timed_out, bir programlama hatasından kaynaklanıyor olabilir.Bu hatalar genellikle kurtarılamaz ve bu nedenle değil yakalandı veya uygulama kodu tarafından işlenen.Yalnızca catch veya programlama hataları tanılamak gerektiğinde uygulama kodunuzda kurtarılamayan hataları işlemek öneririz.Bununla birlikte, çalışma zamanı tarafından tanımlanan özel durum türlerini anlama programlama hataları tanılamanıza yardımcı olabilir.

Özel durum işleme mekanizması çalışma işlevleri tarafından atılan istisnalar olarak çalışma zamanı tarafından atılan özel durumlar için aynıdır.Örneğin, concurrency::receive işlev atar operation_timed_out onu değil aldığınızda ileti belirtilen süre içinde.receive Bir istisna iş işlevinde atar bir görev grubuna geçmesi, çalışma zamanı, özel duruma saklar ve çağıran bağlamına sýralar task_group::wait, structured_task_group::wait, task_group::run_and_wait, ya da structured_task_group::run_and_wait.

Aşağıdaki örnek concurrency::parallel_invoke paralel olarak iki görevleri çalıştırmak için algoritma.İlk görev, beş saniye bekler ve daha sonra ileti arabelleği için bir ileti gönderir.İkinci görev kullanır receive işlevinin aynı ileti arabelleğinden bir ileti almak için üç saniye bekleyin.receive İşlev atar operation_timed_out zaman diliminde iletisi almaz ise.

// 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;
   }
}

Bu örnek aşağıdaki çıktıyı üretir.

The operation timed out.

Uygulamanızın çıkabilecektir önlemek için kodunuzu zamanına çağırdığında özel durumları işleme emin olun.Örneğin, eşzamanlılık çalışma zamanı modülünü kullanan harici kod bir üçüncü taraf kitaplığı çağırdığınızda de özel durumlarý iþlemek.

Top

Birden çok özel durumlar

Birden çok özel bir görev veya paralel algoritması alırsa, filtrenizin arama içerik için yalnızca bir çalışma zamanı sýralar.Çalışma zamanı da sýralar özel durum garanti etmez.

Aşağıdaki örnek parallel_for numaraları konsola yazılır algoritması.Girdi değeri bazı en düşük değerden küçük veya bazı en büyük değerden daha büyük ise, bir istisna atar.Bu örnekte, birden fazla iş işlevlerini bir istisna.

// 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;
   }  
}

Bu örnek için bir örnek çıktı gösterir.

8
2
9
3
10
4
5
6
7
Caught exception: -5: the value is less than the minimum.

Top

İptal etme

Tüm özel durumları bir hata gösterir.Örneğin, arama algoritması, özel durum işleme sonucu bulduğunda, ilişkili görevi durdurmak için kullanabilir.Kodunuzda iptali mekanizmalarını kullanma hakkında daha fazla bilgi için bkz: ppl iptali.

Top

Basit görevleri

Doğrudan zamanlama görev hafif bir görevdir bir concurrency::Scheduler nesnesi.Basit görevleri sıradan Görevler'den daha az ek yük getirir.Bununla birlikte, çalışma zamanı tarafından basit görevleri atılan özel durumları yakalamaz.Bunun yerine, işlemi sonlandırır, varsayılan değer olarak işlenmeyen özel durum işleyicisi tarafından özel durum yakalandı.Bu nedenle, uygun hata işleme mekanizmasını uygulamanızı kullanın.Basit görevler hakkında daha fazla bilgi için bkz: Görev Zamanlayıcı'yı (eşzamanlılık çalışma zamanı).

Top

Zaman uyumsuz aracıları

Basit görevleri gibi çalışma zamanı, zaman uyumsuz aracıları tarafından atılan istisnalar yönetmez.

Türetildiği sınıfı içinde özel durumlarý iþlemek için bir yolu aşağıdaki örnekte gösterildiği concurrency::agent.Bu örnek tanımlar points_agent sınıfı.points_agent::run Yöntemi okuma point nesne ileti arabelleğinden ve konsola yazdırır.run Yöntemi bir istisna onu alırsa, bir NULL işaretçisi.

run Yöntemi içindeki tüm iş çevreleyen bir try-catch blok.catch Blok özel iletinin arabellekte saklar.Uygulama aracı işlemi tamamlandıktan sonra aracısı tarafından bu arabellek okunurken hatayla olup olmadığını denetler.

// 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;
}

Bu örnek aşağıdaki çıktıyı üretir.

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

Çünkü try-catch blok var dışında while döngü, Aracısı biten ilk hata karşılaştığında işleniyor.try-catch Blok was içinde while döngü, Aracısı devam bir hata oluştuktan sonra.

Bu örnek, özel durumlar iletinin arabellekte saklar, böylece çalışırken başka bir bileşen Aracısı hataları izleyebilirsiniz.Bu örnek bir concurrency::single_assignment hata depolamak için nesne.Burada bir aracı birden çok özel işler durumda single_assignment sınıf geçirilen yalnızca ilk mesaj kendisine saklar.Son durum depolamak için kullanmak concurrency::overwrite_buffer sınıfı.Tüm özel durumları depolamak için kullanmak concurrency::unbounded_buffer sınıfı.Bu ileti blokları hakkında daha fazla bilgi için bkz: Zaman uyumsuz ileti blokları.

Zaman uyumsuz aracıları hakkında daha fazla bilgi için bkz: Zaman uyumsuz aracıları.

Top

Özet

Top

Ayrıca bkz.

Kavramlar

Eşzamanlılık çalışma zamanı

Görev paralellik (eşzamanlılık çalışma zamanı)

Paralel algoritmalar

ppl iptali

Görev Zamanlayıcı'yı (eşzamanlılık çalışma zamanı)

Zaman uyumsuz aracıları