Aslında az önce verdiğiniz örnek, oldukça uzun bir işlev kullanıyorsanız, örneğin
//! sleeps for one second and returns 1
auto sleep = [](){
std::this_thread::sleep_for(std::chrono::seconds(1));
return 1;
};
Paketlenmiş görev
A packaged_task
kendi başına başlamaz, onu çağırmanız gerekir:
std::packaged_task<int()> task(sleep);
auto f = task.get_future();
task(); // invoke the function
// You have to wait until task returns. Since task calls sleep
// you will have to wait at least 1 second.
std::cout << "You can see this after 1 second\n";
// However, f.get() will be available, since task has already finished.
std::cout << f.get() << std::endl;
std::async
Öte yandan, std::async
ile launch::async
farklı bir iş parçacığı görevi çalıştırmayı dener:
auto f = std::async(std::launch::async, sleep);
std::cout << "You can see this immediately!\n";
// However, the value of the future will be available after sleep has finished
// so f.get() can block up to 1 second.
std::cout << f.get() << "This will be shown after a second!\n";
sakınca
Ancak async
her şey için kullanmayı denemeden önce , geri dönen geleceğin aşağıdakileri future::~future
engelleyen özel bir paylaşılan duruma sahip olduğunu unutmayın :
std::async(do_work1); // ~future blocks
std::async(do_work2); // ~future blocks
/* output: (assuming that do_work* log their progress)
do_work1() started;
do_work1() stopped;
do_work2() started;
do_work2() stopped;
*/
Dolayısıyla, gerçek eşzamansız olmasını istiyorsanız, geri gönderilenleri saklamanız gerekir future
veya koşullar değişirse sonucu önemsemiyorsanız:
{
auto pizza = std::async(get_pizza);
/* ... */
if(need_to_go)
return; // ~future will block
else
eat(pizza.get());
}
Bu konuda daha fazla bilgi için, Herb Sutter'ın makalesine bakın async
ve~future
sorunu açıklar ve Scott Meyer std::futures
gelen std::async
özel olmayan bilgiler tanımlayan,. Ayrıca, bu davranışın C ++ 14 ve üzeri sürümlerde belirtildiğini , ancak aynı zamanda C ++ 11'de de yaygın olarak uygulandığını unutmayın.
Diğer farklılıklar
Kullanarak std::async
artık görevinizi belirli bir iş parçacığı üzerinde çalıştıramazsınız, burada std::packaged_task
başka iş parçacıklarına taşınabilir.
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::thread myThread(std::move(task),2,3);
std::cout << f.get() << "\n";
Ayrıca, packaged_task
aramadan önce a'nın çağrılması gerekir f.get()
, aksi takdirde gelecek asla hazır olmayacağından programınız donar:
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::cout << f.get() << "\n"; // oops!
task(2,3);
TL; DR
Kullanım std::async
Eğer bazı şeyler yaptık ve onlar bitince gerçekten umurumda değil ve isterseniz std::packaged_task
diğer parçacıkları taşıyın ya da geç onları aramak için şeyler kesmek istiyorum. Veya Christian'dan alıntı yapacak olursak :
Sonuçta a std::packaged_task
, uygulama için sadece daha düşük seviyeli bir özelliktir std::async
(bu nedenle std::async
, diğer daha düşük seviyeli malzemelerle birlikte kullanılmasından daha fazlasını yapabilir std::thread
). Basitçe söylenen a std::packaged_task
, a'ya std::function
bağlıdır std::future
ve std::async
sarar ve a'yı çağırır std::packaged_task
(muhtemelen farklı bir dizide).