वास्तव में आपने जो उदाहरण दिया है वह अंतर दिखाता है यदि आप एक लंबे समय के फ़ंक्शन का उपयोग करते हैं, जैसे कि
//! sleeps for one second and returns 1
auto sleep = [](){
std::this_thread::sleep_for(std::chrono::seconds(1));
return 1;
};
पैक किए गए कार्य
A packaged_task
इसकी शुरुआत खुद नहीं करेगा, आपको इसे लागू करना होगा:
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
दूसरी ओर, std::async
के साथ launch::async
एक अलग थ्रेड में काम चलाने का प्रयास करेंगे:
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";
कमी
लेकिन इससे पहले कि आप async
सब कुछ के लिए उपयोग करने का प्रयास करें , ध्यान रखें कि लौटे भविष्य में एक विशेष साझा स्थिति है, जो उस future::~future
ब्लॉक की मांग करती है:
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;
*/
इसलिए यदि आप वास्तविक अतुल्यकालिक चाहते हैं तो आपको लौटाए रखने की आवश्यकता है future
, या यदि आप परिस्थितियों को बदलते हैं तो परिणाम की परवाह नहीं करते हैं:
{
auto pizza = std::async(get_pizza);
/* ... */
if(need_to_go)
return; // ~future will block
else
eat(pizza.get());
}
इस बारे में अधिक जानकारी के लिए, हर्ब सुतर की आलेख देखें async
और~future
है, जो समस्या का वर्णन करता है, और स्कॉट मेयर की std::futures
से std::async
विशेष नहीं कर रहे हैं , जो अंतर्दृष्टि वर्णन करता है। यह भी ध्यान दें कि यह व्यवहार C ++ 14 और ऊपर निर्दिष्ट किया गया था , लेकिन सामान्यतः C ++ 11 में भी लागू किया गया है।
आगे मतभेद
उपयोग करने से std::async
आप अपने कार्य को एक विशेष धागे पर नहीं चला सकते हैं, जहां std::packaged_task
अन्य धागे में स्थानांतरित किया जा सकता है।
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";
इसके अलावा, packaged_task
कॉल करने से पहले आपको इनवाइट करना होगा f.get()
, अन्यथा आप प्रोग्राम को फ्रीज कर देंगे क्योंकि भविष्य कभी तैयार नहीं होगा:
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::cout << f.get() << "\n"; // oops!
task(2,3);
टी एल; डॉ
std::async
यदि आप कुछ काम करना चाहते हैं तो उपयोग करें और जब वे कर रहे हों तो वास्तव में परवाह न करें, और std::packaged_task
यदि आप चीजों को अन्य थ्रेड्स में स्थानांतरित करने के लिए या बाद में उन्हें कॉल करना चाहते हैं। या, ईसाई को उद्धृत करने के लिए :
अंत में ए std::packaged_task
लागू करने के लिए सिर्फ एक निचले स्तर की विशेषता है std::async
(यही कारण है कि यह std::async
अन्य निचले स्तर के सामान, जैसे कि एक साथ उपयोग किए जाने से अधिक कर सकता है std::thread
)। सीधे शब्दों में बोले गए एक std::packaged_task
एक है std::function
एक से जुड़ा हुआ std::future
है और std::async
wraps और एक कॉल std::packaged_task
(संभवतः एक अलग धागे में)।