मैं vc2011 का उपयोग कर रहा हूं और यह std :: async (std :: launch :: async, ...) को थोड़ा सा गड़बड़ कर देता है (कभी-कभी यह नए धागे को नहीं बढ़ाता है और उन्हें समानांतर में चलाता है, लेकिन इसके बजाय पुन: उपयोग करता है धागे और एक के बाद एक काम करता है)। जब मैं महंगे नेटवर्क कॉल कर रहा हूं तो यह बहुत धीमा है। तो मैंने सोचा कि मैं अपना स्वयं का एसिंक फ़ंक्शन लिखूंगा। मैं हालांकि अटक गया हूँ, std :: वादा कहाँ रहना चाहिए? 1) थ्रेड फ़ंक्शन, 2) async फ़ंक्शन, या 3) कॉलर फ़ंक्शन।std :: async को अपने संस्करण के साथ बदलना, लेकिन std :: वादा कहाँ रहना चाहिए?
कोड:
#include <future>
#include <thread>
#include <iostream>
#include <string>
#include <vector>
std::string thFun() {
throw std::exception("bang!");
return "val";
}
std::future<std::string> myasync(std::promise<std::string>& prms) {
//std::future<std::string> myasync() {
//std::promise<std::string> prms; //needs to outlive thread. How?
std::future<std::string> fut = prms.get_future();
std::thread th([&](){
//std::promise<std::string> prms; //need to return a future before...
try {
std::string val = thFun();
prms.set_value(val);
} catch(...) {
prms.set_exception(std::current_exception());
}
});
th.detach();
return fut;
}
int main() {
std::promise<std::string> prms; //I really want the promise hidden iway in the myasync func and not live here in caller code but the promise needs to outlive myasync and live as long as the thread. How do I do this?
auto fut = myasync(prms);
//auto fut = myasync(); //Exception: future already retrieved
try {
auto res = fut.get();
std::cout << "Result: " << res << std::endl;
} catch(const std::exception& exc) {
std::cout << "Exception: " << exc.what() << std::endl;
}
}
मैं नहीं कर सकते तथ्य यह है कि std :: वादा async समारोह से अधिक जीवित करने की जरूरत है अतीत मिलता है (और धागे के रूप में के रूप में लंबे समय तक जीवित) प्रतीत होते हैं इसलिए वादा नहीं कर सकते एक के रूप में जीवित async func में स्थानीय चर। लेकिन std :: वादा कॉलर कोड में नहीं रहना चाहिए, क्योंकि कॉलर को केवल वायदा के बारे में जानना आवश्यक है। और मैं नहीं जानता कि वादा को थ्रेड फ़ंक्शन में कैसे बनाया जाए क्योंकि एसिंक को भविष्य को वापस करने की आवश्यकता है इससे पहले कि यह थ्रेड func भी कॉल करे। मैं इस पर अपने सिर खरोंच कर रहा हूँ।
किसी को भी कोई विचार है?
संपादित करें: मैं इसे यहां हाइलाइट कर रहा हूं क्योंकि शीर्ष टिप्पणी थोड़ा गलत है। जबकि std :: asycn के लिए डिफ़ॉल्ट को dererred मोड होने की अनुमति है, जब std :: launch :: async की लॉन्च नीति स्पष्ट रूप से सेट की जाती है, तो इसे "जैसे" थ्रेड उत्पन्न होते हैं और एक साथ चलते हैं (एन में शब्द देखें .cppreference.com/w/सीपीपी/धागा/async)। पेस्टबिन.com/5dWCjjNY में एक मामले के लिए उदाहरण देखें जहां यह बनाम 20011 में व्यवहार नहीं किया गया है। समाधान बहुत अच्छा काम करता है और 10.1
संपादित करें 2: एमएस ने बग को ठीक किया है। यहाँ और जानकारी:
future<string> myasync()
{
auto prms = make_shared<promise<string>>();
future<string> fut = prms->get_future();
thread th([=](){
try {
string val = thFun();
// ...
prms->set_value(val);
} catch(...) {
prms->set_exception(current_exception());
}
});
th.detach();
return fut;
}
ढेर पर वादा आवंटित, और फिर लैम्ब्डा को पारित-दर-मूल्य [=]
एक shared_ptr इसे करने के लिए के माध्यम से: https://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread
"कभी-कभी यह नए धागे को नहीं बढ़ाता है और उन्हें समानांतर में चलाता है, लेकिन इसके बजाय धागे का उपयोग करता है और एक के बाद एक कार्य चलाता है" यह छोटी नहीं है; इस तरह इसे काम करने की अनुमति है। विनिर्देश में कोई गारंटी नहीं है कि किसी विशेष एसिंक कॉल को पूर्व या भविष्य एसिंक कॉल से अलग थ्रेड में चलाया जाएगा।यदि आप इसे चाहते हैं, तो बस धागे का एक गुच्छा बनाएं, उन्हें एक कंटेनर में चिपकाएं, और फिर जब आप डेटा वापस प्राप्त करना चाहते हैं तो उनसे जुड़ें। –
भविष्य में, कृपया बाहरी कोड से जोड़ने के बजाय अपने कोड को सीधे अपने प्रश्न में रखें। – ildjarn
@ निकोल। क्या आपको यकीन है? जैसा कि मैं समझता हूं कि std :: launch :: async का उपयोग करते समय इसे कार्य करना चाहिए जैसे कि धागा उत्पन्न हुआ था। Http://en.cppreference.com/w/cpp/thread/async के अनुसार "यदि नीति और std :: launch :: async! = 0 (async बिट सेट है), निष्पादन के एक नए धागे को स्पॉन्स करता है जैसे कि std :: thread (f, args ...), सिवाय इसके कि यदि फ़ंक्शन एफ एक मान देता है या अपवाद फेंकता है, तो यह साझा स्थिति में संग्रहीत किया जाता है जो std :: भविष्य के माध्यम से सुलभ होता है कि async कॉलर पर वापस आती है। " – petke