Aracılığıyla paylaş


PPL'de İptal

Bu belgede Paralel Desen kitaplığındaki (PPL) iptal etme rolü, paralel çalışmanın nasıl iptal edileceği ve paralel çalışmanın ne zaman iptal edileceğinin nasıl belirleneceği açıklanır.

Dekont

Çalışma zamanı, iptali uygulamak için özel durum işlemeyi kullanır. Kodunuzda bu özel durumları yakalamayın veya işlemeyin. Ayrıca, görevleriniz için işlev gövdelerine özel durum açısından güvenli kod yazmanızı öneririz. Örneğin, bir görevin gövdesinde bir özel durum oluştuğunda kaynakların doğru şekilde işlendiğinden emin olmak için Kaynak Alma Başlatmadır (RAII) desenini kullanabilirsiniz. İptal edilebilir bir görevdeki bir kaynağı temizlemek için RAII desenini kullanan eksiksiz bir örnek için bkz . İzlenecek Yol: Kullanıcı Arabirimi İş Parçacığından Çalışma Kaldırma.

Önemli Noktalar

Bu Belgede

Paralel çalışma ağaçları

PPL, ayrıntılı görevleri ve hesaplamaları yönetmek için görevleri ve görev gruplarını kullanır. Paralel çalışma ağaçlarını oluşturmak için görev gruplarını iç içe yerleştirebilirsiniz. Aşağıdaki çizimde paralel bir çalışma ağacı gösterilmektedir. Bu çizimde, tg1tg2 görev gruplarını temsil eder; t1, t2, t3, t4ve t5 görev gruplarının gerçekleştirdiği çalışmayı temsil eder.

A parallel work tree.

Aşağıdaki örnekte, çizimde ağacı oluşturmak için gereken kod gösterilmektedir. Bu örnekte tg1 ve tg2 eşzamanlılık::structured_task_group nesneleridir; t1, t2, t3, t4ve t5 eşzamanlılık::task_handle nesneleridir.

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

Benzer bir iş ağacı oluşturmak için eşzamanlılık::task_group sınıfını da kullanabilirsiniz. concurrency::task sınıfı, bir iş ağacının destesini de destekler. Ancak, bir task ağaç bir bağımlılık ağacıdır. Bir task ağaçta, gelecekteki çalışmalar geçerli çalışmadan sonra tamamlar. Bir görev grubu ağacında, iç çalışma dış çalışmadan önce tamamlar. Görevler ve görev grupları arasındaki farklar hakkında daha fazla bilgi için bkz . Görev Paralelliği.

[Üst]

Paralel Görevleri İptal Etme

Paralel çalışmayı iptal etmenin birden çok yolu vardır. Tercih edilen yol, iptal belirteci kullanmaktır. Görev grupları eşzamanlılık::task_group::cancel yöntemini ve eşzamanlılık::structured_task_group::cancel yöntemini de destekler. Son yol, bir görev çalışma işlevinin gövdesinde bir özel durum oluşturmaktır. Hangi yöntemi seçerseniz seçin, iptalin hemen gerçekleşmediğini anlayın. Bir görev veya görev grubu iptal edilirse yeni çalışma başlatılmasa da, etkin çalışma iptali denetlemeli ve yanıt vermelidir.

Paralel görevleri iptal eden diğer örnekler için bkz. İzlenecek yol: Görevleri ve XML HTTP İsteklerini Kullanma Bağlan, Nasıl yapılır: Paralel Döngüden Ayrılmak için İptali Kullanma ve Nasıl Yapılır: Paralel Döngüden Ayrılmak için Özel Durum İşlemeyi Kullanma.

Paralel Çalışmayı İptal Etmek için İptal Belirteci Kullanma

task, task_groupve structured_task_group sınıfları, iptal belirteçleri kullanarak iptali destekler. PPL, bu amaçla eşzamanlılık::cancellation_token_source ve eşzamanlılık::cancellation_token sınıflarını tanımlar. çalışmayı iptal etmek için bir iptal belirteci kullandığınızda, çalışma zamanı bu belirtece abone olan yeni çalışmayı başlatmaz. Zaten etkin olan çalışma, iptal belirtecini izlemek ve ne zaman durdurabilirse durdurmak için is_canceled üye işlevini kullanabilir.

İptal işlemini başlatmak için eşzamanlılık::cancellation_token_source::cancel yöntemini çağırın. İptale şu yollarla yanıt verirsiniz:

  • Nesneler için task eşzamanlılık::cancel_current_task işlevini kullanın. cancel_current_task geçerli görevi ve değer tabanlı devamlılıklarından herhangi birini iptal eder. (Görevle veya devamlarıyla ilişkili iptal belirtecini iptal etmez.)

  • Görev grupları ve paralel algoritmalar için concurrency::is_current_task_group_canceling işlevini kullanarak iptali algılayın ve bu işlev döndürdüğünde truegörev gövdesinden mümkün olan en kısa sürede dönün. (Görev grubundan arama cancel_current_task yapma.)

Aşağıdaki örnek, görev iptali için ilk temel deseni gösterir. Görev gövdesi zaman zaman döngü içinde iptali denetler.

// task-basic-cancellation.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <concrt.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 (token.is_canceled())
            {
                // 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.
*/

işlevi cancel_current_task oluşturur; bu nedenle, geçerli döngüden veya işlevden açıkça dönmeniz gerekmez.

Bahşiş

Alternatif olarak, yerine eşzamanlılık::interruption_point işlevini cancel_current_taskçağırabilirsiniz.

görevi iptal edilmiş duruma geçirdiğinden iptale yanıt verirken çağrı cancel_current_task yapmak önemlidir. çağrısı cancel_current_taskyerine erken dönerseniz, işlem tamamlanmış duruma geçirilir ve değer tabanlı devamlılıklar çalıştırılır.

Dikkat

Kodunuzdan asla atmayın task_canceled . Bunun yerine ara cancel_current_task .

Bir görev iptal edildi durumunda sona erdiğinde eşzamanlılık::task::get yöntemi eşzamanlılık::task_canceled oluşturur. (Buna karşılık eşzamanlılık::task::wait işlevi task_status::canceled döndürür ve atılmaz.) Aşağıdaki örnekte, görev tabanlı devamlılık için bu davranış gösterilmektedir. Öncül görev iptal edilse bile, görev tabanlı devamlılık her zaman çağrılır.

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

Değer tabanlı devamlılıklar, açık bir belirteçle oluşturulmadıkları sürece öncül görevlerinin belirtecini devraldığından, öncül görev yürütülürken bile devamlılıklar hemen iptal edilen duruma girer. Bu nedenle, iptal sonrasında öncül görev tarafından oluşan herhangi bir özel durum devamlılık görevlerine yayılmaz. İptal her zaman öncül görevin durumunu geçersiz kılar. Aşağıdaki örnek öncekine benzer, ancak değer tabanlı devamlılık davranışını gösterir.

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

Dikkat

Oluşturucuya veya eşzamanlılık::create_task işlevine taskbir iptal belirteci geçirmezseniz, bu görev iptal edilemez. Ayrıca, tüm görevleri aynı anda iptal etmek için iç içe görevlerin (başka bir görevin gövdesinde oluşturulan görevler) oluşturucusunun aynı iptal belirtecini geçirmeniz gerekir.

İptal belirteci iptal edildiğinde rastgele kod çalıştırmak isteyebilirsiniz. Örneğin, kullanıcınız işlemi iptal etmek için kullanıcı arabiriminde bir İptal düğmesi seçerse, kullanıcı başka bir işlem başlatana kadar bu düğmeyi devre dışı bırakabilirsiniz. Aşağıdaki örnekte, iptal belirteci iptal edildiğinde çalışan bir geri çağırma işlevini kaydetmek için eşzamanlılık::cancellation_token::register_callback yönteminin nasıl kullanılacağı gösterilmektedir.

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

Görev Paralelliği belgesi, değer tabanlı ve görev tabanlı devamlılıklar arasındaki farkı açıklar. Bir devamlılık görevine nesne sağlamazsanız cancellation_token , devamlılık iptal belirtecini aşağıdaki yollarla öncül görevden devralır:

  • Değer tabanlı devamlılık her zaman öncül görevin iptal belirtecini devralır.

  • Görev tabanlı devamlılık hiçbir zaman öncül görevin iptal belirtecini devralmaz. Görev tabanlı devamlılığı iptal edilebilir hale getirmenin tek yolu açıkça bir iptal belirteci geçirmektir.

Bu davranışlar hatalı bir görevden (yani özel durum oluşturan görevden) etkilenmez. Bu durumda, değer tabanlı devamlılık iptal edilir; görev tabanlı devamlılık iptal edilmiyor.

Dikkat

Başka bir görevde oluşturulan bir görev (başka bir deyişle, iç içe görev), üst görevin iptal belirtecini devralmıyor. Yalnızca değer tabanlı bir devamlılık, öncül görevinin iptal belirtecini devralır.

Bir veya structured_task_group nesnesinin oluşturucusunun iptal belirtecini task_group de sağlayabilirsiniz. Bunun önemli bir yönü, alt görev gruplarının bu iptal belirtecini devralmasıdır. Bu kavramı çağırmak üzere çalıştırmak üzere concurrency::run_with_cancellation_token işlevini kullanarak gösteren bir örnek içinparallel_for, bu belgenin devamında yer alan Paralel Algoritmaları İptal Etme bölümüne bakın.

[Üst]

İptal Belirteçleri ve Görev Oluşturma

Eşzamanlılık::when_all ve eşzamanlılık::when_any işlevleri, ortak desenleri uygulamak için birden çok görev oluşturmanıza yardımcı olabilir. Bu bölümde, bu işlevlerin iptal belirteçleriyle nasıl çalıştığı açıklanmaktadır.

ve when_any işlevine when_all bir iptal belirteci sağladığınızda, bu işlev yalnızca iptal belirteci iptal edildiğinde veya katılımcı görevlerinden biri iptal edilmiş durumda sona erdiğinde veya bir özel durum oluşturursa iptal edilir.

İşlev, when_all bir iptal belirteci sağlamadığınızda genel işlemi oluşturan her görevden iptal belirtecini devralır. Bu belirteçlerden when_all herhangi biri iptal edildiğinde ve katılımcı görevlerinden en az biri henüz başlatılmadığında veya çalıştırıldığında, içinden döndürülen görev iptal edilir. Görevlerden biri özel durum oluşturursa benzer bir davranış oluşur. Bu özel durumla döndürülen görev when_all hemen iptal edilir.

Çalışma zamanı, görev tamamlandığında işlevden when_any döndürülen görev için iptal belirtecini seçer. Katılımcı görevlerinden hiçbiri tamamlanmış durumda tamamlanmazsa ve görevlerden biri veya daha fazlası özel durum oluşturursa, atan görevlerden biri tamamlamak when_any için seçilir ve son görevin belirteci olarak belirteci seçilir. Birden fazla görev tamamlanmış durumda biterse, görevden when_any döndürülen görev tamamlanmış durumda biter. Çalışma zamanı, tamamlanma sırasında belirteci iptal edilmeyen tamamlanmış bir görevi seçmeye çalışır, böylece diğer yürütme görevleri daha sonraki bir noktada tamamlansa bile, döndürülen görev when_any hemen iptal edilmez.

[Üst]

Paralel Çalışmayı İptal Etmek için cancel Yöntemini Kullanma

Eşzamanlılık::task_group::cancel ve eşzamanlılık::structured_task_group::cancel yöntemleri bir görev grubunu iptal edildi durumuna ayarlar. çağrısı cancelyaptıktan sonra, görev grubu gelecekteki görevleri başlatmaz. cancel Yöntemler birden çok alt görev tarafından çağrılabilir. İptal edilen bir görev eşzamanlılık::task_group::wait ve eşzamanlılık::structured_task_group::wait yöntemlerinin eşzamanlılık::canceled döndürmesine neden olur.

Bir görev grubu iptal edilirse, her alt görevden çalışma zamanına yapılan çağrılar bir kesinti noktası tetikleyebilir ve bu da çalışma zamanının etkin görevleri iptal etmek için bir iç özel durum türü oluşturmasına ve yakalamasına neden olur. Eşzamanlılık Çalışma Zamanı belirli kesinti noktalarını tanımlamaz; çalışma zamanına yapılan herhangi bir çağrıda oluşabilir. Çalışma zamanının iptal gerçekleştirmek için attığı özel durumları işlemesi gerekir. Bu nedenle, bir görevin gövdesinde bilinmeyen özel durumları işlemeyin.

Bir alt görev zaman alan bir işlem gerçekleştirirse ve çalışma zamanını çağırmazsa, iptali düzenli aralıklarla denetlemeli ve zamanında çıkmalıdır. Aşağıdaki örnekte, işin ne zaman iptal edileceğini belirlemenin bir yolu gösterilmektedir. Görev t4 , bir hatayla karşılaştığında üst görev grubunu iptal eder. Görev t5 bazen iptali structured_task_group::is_canceling denetlemek için yöntemini çağırır. Üst görev grubu iptal edilirse, görev t5 bir ileti yazdırır ve çıkar.

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();

Bu örnek, görev döngüsünün her 100. yinelemesinde iptali denetler. İptal etme durumunu denetleme sıklığı, görevinizin gerçekleştirdiği çalışma miktarına ve görevlerin iptale yanıt vermesi için ne kadar hızlı ihtiyacınız olduğuna bağlıdır.

Üst görev grubu nesnesine erişiminiz yoksa, üst görev grubunun iptal edilip edilmediğini belirlemek için eşzamanlılık::is_current_task_group_canceling işlevini çağırın.

cancel yöntemi yalnızca alt görevleri etkiler. Örneğin, paralel çalışma ağacının çiziminde görev grubunu tg1 iptal ederseniz, ağaçtaki tüm görevler (t1, t2, t3, t4ve t5) etkilenir. İç içe görev grubunu iptal ederseniz, tg2yalnızca görevler t4 ve t5 etkilenir.

yöntemini çağırdığınızda cancel , tüm alt görev grupları da iptal edilir. Ancak iptal, paralel bir iş ağacındaki görev grubunun hiçbir ebeveynini etkilemez. Aşağıdaki örneklerde paralel iş ağacı çizimini temel alarak bunu gösterilmiştir.

Bu örneklerden ilki, görev grubunun tg2alt öğesi olan görevi t4için bir çalışma işlevi oluşturur. İş işlevi, bir döngü içinde işlevi work çağırır. Herhangi bir çağrısı work başarısız olursa, görev üst görev grubunu iptal eder. Bu, görev grubunun tg2 iptal edildi durumuna girmesine neden olur, ancak görev grubunu tg1iptal etmez.

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

Bu ikinci örnek, görevin görev grubunu tg1iptal etmemesi dışında ilk örnek gibi görünür. Bu, ağaçtaki (t1, t2, , t3t4ve t5) tüm görevleri etkiler.

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 Sınıfı iş parçacığı açısından güvenli değildir. Bu nedenle, üst structured_task_group nesnesinin yöntemini çağıran bir alt görev belirtilmemiş davranış üretir. Bu kuralın structured_task_group::cancel özel durumları ve eşzamanlılığı::structured_task_group::is_canceling yöntemleridir. Alt görev, üst görev grubunu iptal etmek ve iptal olup olmadığını denetlemek için bu yöntemleri çağırabilir.

Dikkat

Bir nesnenin alt öğesi olarak çalışan bir görev grubu tarafından gerçekleştirilen çalışmayı iptal etmek için iptal task belirteci kullanabilirsiniz, ancak bir görev grubunda çalışan nesneleri iptal task etmek için veya structured_task_group::cancel yöntemlerini kullanamazsınıztask_group::cancel.

[Üst]

Paralel Çalışmayı İptal Etmek için Özel Durumlar Kullanma

İptal belirteçlerinin ve yönteminin kullanımı, paralel bir iş ağacını cancel iptal etmede özel durum işlemeden daha verimlidir. İptal belirteçleri ve cancel yöntemi, bir görevi ve alt görevleri yukarıdan aşağıya doğru iptal eder. Buna karşılık, özel durum işleme aşağıdan yukarıya doğru çalışır ve özel durum yukarı doğru yayıldıkça her alt görev grubunu bağımsız olarak iptal etmelidir. Özel Durum İşleme konusu, Eşzamanlılık Çalışma Zamanı'nın hataları iletmek için özel durumları nasıl kullandığını açıklar. Ancak, tüm özel durumlar bir hataya işaret etmemektedir. Örneğin, arama algoritması sonucu bulduğunda ilişkili görevini iptal edebilir. Ancak, daha önce belirtildiği gibi, özel durum işleme paralel çalışmayı iptal etmek için yöntemini kullanmaktan cancel daha az verimlidir.

Dikkat

Paralel çalışmayı yalnızca gerektiğinde iptal etmek için özel durumlar kullanmanızı öneririz. İptal belirteçleri ve görev grubu cancel yöntemleri daha verimlidir ve hataya daha az eğilimli olur.

Görev grubuna geçirdiğiniz bir iş işlevinin gövdesine özel durum oluşturduğunuzda, çalışma zamanı bu özel durumu depolar ve özel durumu görev grubunun bitmesini bekleyen bağlama göre sıralar. yönteminde cancel olduğu gibi, çalışma zamanı henüz başlatılmamış görevleri atar ve yeni görevleri kabul etmez.

Bu üçüncü örnek ikincisine benzer, ancak görev t4 , görev grubunu tg2iptal etmek için bir özel durum oluşturur. Bu örnekte, görev grubu tg2 alt görevlerinin tamamlanmasını beklediğinde iptal olup olmadığını denetlemek için bircatchtry-blok kullanılır. İlk örnekte olduğu gibi, bu da görev grubunun tg2 iptal edilmiş duruma girmesine neden olur, ancak görev grubunu tg1iptal etmez.

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

Bu dördüncü örnek, iş ağacının tamamını iptal etmek için özel durum işlemeyi kullanır. Örnek, görev grubu alt görevlerinin tamamlanmasını beklerken görev grubu tg1tg2 alt görevlerini beklerken özel durumu yakalar. İkinci örnekte olduğu gibi, bu da ağaçtaki tg1 her iki görev grubunun da tg2iptal edilmiş duruma girmesine neden olur.

// 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 Bir alt görev özel durum oluştururken ve structured_task_group::wait yöntemleri attığından, onlardan bir dönüş değeri almazsınız.

[Üst]

Paralel Algoritmaları İptal Etme

PPL'deki paralel algoritmalar, örneğin, parallel_forgörev gruplarını temel alır. Bu nedenle, paralel algoritmayı iptal etmek için aynı tekniklerin çoğunu kullanabilirsiniz.

Aşağıdaki örneklerde paralel algoritmayı iptal etmenin çeşitli yolları gösterilmektedir.

Aşağıdaki örnek algoritmayı run_with_cancellation_token çağırmak parallel_for için işlevini kullanır. İşlev, run_with_cancellation_token bağımsız değişken olarak bir iptal belirteci alır ve sağlanan iş işlevini zaman uyumlu olarak çağırır. Paralel algoritmalar görevler üzerine oluşturulduğundan, üst görevin iptal belirtecini devralır. Bu nedenle iptale parallel_for yanıt verebilir.

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

Aşağıdaki örnek, algoritmayı çağırmak parallel_for için eşzamanlılık::structured_task_group::run_and_wait yöntemini kullanır. yöntemi, structured_task_group::run_and_wait sağlanan görevin tamamlanmasını bekler. structured_task_group nesnesi, iş işlevinin görevi iptal etmesine olanak tanır.

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

Bu örnek aşağıdaki çıkışı oluşturur.

The task group status is: canceled.

Aşağıdaki örnek, bir parallel_for döngünün iptali için özel durum işlemeyi kullanır. Çalışma zamanı, özel durumu çağıran bağlama göre sıralar.

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

Bu örnek aşağıdaki çıkışı oluşturur.

Caught 50

Aşağıdaki örnekte, bir döngüde iptali koordine etmek için Boole parallel_for bayrağı kullanılır. Bu örnek, genel görev kümesini iptal etmek için yöntemi veya özel durum işlemeyi kullanmadığından cancel her görev çalıştırılır. Bu nedenle, bu teknik bir iptal mekanizmasından daha fazla hesaplama yüküne sahip olabilir.

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

Her iptal yönteminin diğerlerine göre avantajları vardır. Özel gereksinimlerinize uygun yöntemi seçin.

[Üst]

İptal Kullanmama Zamanları

bir grup ilgili görevden her üye zamanında çıkabildiğinde iptalin kullanılması uygundur. Ancak, iptalin uygulamanız için uygun olmayabileceği bazı senaryolar vardır. Örneğin, görev iptali işbirliğine bağlı olduğundan, tek tek herhangi bir görev engellenirse genel görev kümesi iptal olmaz. Örneğin, bir görev henüz başlatılmamışsa ancak başka bir etkin görevin engelini kaldırırsa, görev grubu iptal edilirse başlatılmaz. Bu, uygulamanızda kilitlenme oluşmasına neden olabilir. İptal kullanımının uygun olmayabileceği ikinci bir örnek, bir görevin iptal edilmesi ancak alt görevinin kaynak boşaltma gibi önemli bir işlem gerçekleştirmesidir. Üst görev iptal edildiğinde genel görev kümesi iptal edildiğinden, bu işlem yürütülmeyecek. Bu noktayı gösteren bir örnek için Paralel Desen kitaplığındaki En İyi Yöntemler konusunun İptal ve Özel Durum İşlemenin Nesne Yok Etme Durumunu Nasıl Etkilediğini Anlama bölümüne bakın.

[Üst]

Title Tanım
Nasıl yapılır: Paralel Bir Döngüden Kurtulmak için İptal Paralel arama algoritması uygulamak için iptalin nasıl kullanılacağını gösterir.
Nasıl yapılır: Paralel Bir Döngüden Kurtulmak için Özel Durum İşlemeyi Kullanma Temel ağaç yapısı için arama algoritması yazmak için sınıfının nasıl kullanılacağını task_group gösterir.
Özel Durum İşleme Çalışma zamanının görev grupları, basit görevler ve zaman uyumsuz aracılar tarafından oluşan özel durumları nasıl işlediğini ve uygulamalarınızdaki özel durumlara nasıl yanıt vereceğini açıklar.
Görev Paralelliği Görevlerin görev gruplarıyla ilişkisini ve uygulamalarınızda yapılandırılmamış ve yapılandırılmış görevleri nasıl kullanabileceğinizi açıklar.
Paralel Algoritmalar Veri koleksiyonları üzerinde eşzamanlı olarak çalışma gerçekleştiren paralel algoritmaları açıklar
Paralel Desen Kitaplığı (PPL) Paralel Desenler Kitaplığı'na genel bir bakış sağlar.

Başvuru

task Sınıfı (Eşzamanlılık Çalışma Zamanı)

cancellation_token_source Sınıfı

cancellation_token Sınıfı

task_group Sınıfı

structured_task_group Sınıfı

parallel_for İşlevi