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.
Not
Ç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
İptal, işbirliğine yöneliktir ve iptal isteğinde bulunan kod ile iptale yanıt veren görev arasında koordinasyon sağlar.
Mümkün olduğunda, çalışmayı iptal etmek için iptal belirteçlerini kullanın. concurrency::cancellation_token sınıfı bir iptal belirteci tanımlar.
İptal belirteçlerini kullandığınızda, iptali başlatmak için eşzamanlılık::cancellation_token_source::cancel yöntemini ve iptale yanıt vermek için eşzamanlılık::cancel_current_task işlevini kullanın. Başka bir görevin iptal isteğinde bulunup bulunmadığını denetlemek için eşzamanlılık::cancellation_token::is_canceled yöntemini kullanın.
İptal hemen gerçekleşmez. 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.
Değer tabanlı devamlılık, öncül görevinin iptal belirtecini devralır. Görev tabanlı devamlılık hiçbir zaman öncül görevinin belirtecini devralmaz.
Bir nesneyi alan
cancellation_token
ancak işlemin iptal edilebilir olmasını istemediğiniz bir oluşturucuyu veya işlevi çağırırken concurrency::cancellation_token::none yöntemini kullanın. Ayrıca, eşzamanlılık::görev oluşturucusunun veya eşzamanlılık::create_task işlevine bir iptal belirteci geçirmezseniz, bu görev iptal edilemez.
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, tg1
tg2
görev gruplarını temsil eder; t1
, t2
, t3
, t4
ve t5
görev gruplarının gerçekleştirdiği çalışmayı temsil eder.
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
, t4
ve 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 Kullanarak Bağlanma, 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_group
ve 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
true
görev gövdesinden mümkün olan en kısa sürede dönün. (Görev grubundan aramacancel_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.
İpucu
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_task
yerine 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 task
bir 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.
İpucu
Bir nesneyi alan cancellation_token
bir oluşturucuyu veya işlevi çağırdığınızda ve işlemin iptal edilebilir olmasını istemediğinizde concurrency::cancellation_token::none yöntemini kullanın.
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ı cancel
yaptı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
, t4
ve t5
) etkilenir. İç içe görev grubunu iptal ederseniz, tg2
yalnı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 tg2
alt öğesi olan görevi t4
iç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 tg1
iptal 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 tg1
iptal etmemesi dışında ilk örnek gibi görünür. Bu, ağaçtaki (t1
, t2
, , t3
t4
ve 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 tg2
iptal 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 bircatch
try
-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 tg1
iptal 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 tg1
tg2
alt görevlerini beklerken özel durumu yakalar. İkinci örnekte olduğu gibi, bu da ağaçtaki tg1
her iki görev grubunun da tg2
iptal 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_for
gö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]
İlgili Konular'a
Ünvan | Açıklama |
---|---|
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ı)