2013-06-24 19 views
5

मैं काफी आसान होना चाहिए क्या करना चाहते हैं, लेकिन मैं इसे नहीं मिलता है क्या ...उपयोग सदस्य समारोह :: packaged_task

सभी मैं करना चाहता हूँ में एक वर्ग के एक सदस्य समारोह शुरू करने के लिए है समय में कुछ निश्चित बिंदु पर पृष्ठभूमि । उस समारोह का नतीजा भी "बाहरी रूप से" उपलब्ध होना चाहिए। तो मैं कन्स्ट्रक्टर में कार्य तैयार करना चाहता हूं (भविष्य परिवर्तनीय सेट कर रहा हूं ...) और इसे बाद के बिंदु पर शुरू करना चाहता हूं।

मैंने std को गठबंधन करने की कोशिश की :((packaged_task | async | भविष्य) लेकिन मुझे इसे काम नहीं मिला।

यह स्निपेट संकलन नहीं होगा, लेकिन मैं यह पता चलता है कि मैं क्या करना चाहते हैं लगता है: पहले से

class foo { 
private: 
    // This function shall run in background as a thread 
    // when it gets triggered to start at some certain point 
    bool do_something() { return true; } 

    std::packaged_task<bool()> task; 
    std::future<bool> result; 

public: 
    foo() : 
    task(do_something), // yes, that's wrong, but how to do it right? 
    result(task.get_future()) 
    { 
    // do some initialization stuff 
    ..... 
    } 
    ~foo() {} 

    void start() { 
    // Start Task as asynchron thread 
    std::async as(std::launch::async, task); // Also doesn't work... 
    } 

    // This function should return the result of do_something 
    bool get_result() { return result.get(); } 
}; 

धन्यवाद! इसके अलावा

#include <functional> // For std::bind() 

foo() : 
    task(std::bind(&foo::do_something, this)), 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    result(task.get_future()) 
{ 
    // ... 
} 

, आप यहाँ गलत बात कर रहे हैं:

+0

'std :: async' एक कार्य है, एक प्रकार –

उत्तर

8

बस std::bind() का उपयोग

std::async as(std::launch::async, task) 
//   ^^ 
//   Trying to declare a variable? 

आप क्या चाहते हैं के बाद से है, std::async() समारोह फोन नहीं करने के लिए एक का एक उद्देश्य घोषित करने के लिए (गैर-मौजूदा) टाइप std::async()। अपने कार्य std::async() के अजीब व्यवहार की वजह से जब लौटे भविष्य त्याग दिया जाता है, तो पहले कदम के रूप में यह परिवर्तन:

std::async(std::launch::async, task) 

सूचना यह है कि इस कार्य को अतुल्यकालिक रूप से चलाने के लिए पर्याप्त नहीं होगा हमेशा निष्पादित किया जाएगा जैसे कि आपने इसे सिंक्रनाइज़ करना शुरू किया - लौटा भविष्य की वस्तु का विनाश ऑपरेशन पूरा होने तक अवरुद्ध होगा।

result = std::async(std::launch::async, task); 
// ^^^^^^^^ 

(*) मैं: (*)

यह पिछले समस्या को हल करने के लिए, आप (बल्कि result भविष्य निर्माण पर std::packaged_task::get_future() द्वारा वापस करने के लिए बताए से) अपने result सदस्य चर में लौटे भविष्य पकड़ कर सकते हैं सोचें कि एमएसवीसी इस विनिर्देश को अनदेखा करता है और वास्तव में कार्य को असीमित रूप से निष्पादित करता है। तो यदि आप वीएस2012 के साथ काम कर रहे हैं, तो आप इस समस्या से पीड़ित नहीं हो सकते हैं।

संपादित करें:

As correctly mentioned by Praetorian in his answer, ऊपर अभी भी समस्याग्रस्त किया जाएगा packaged_task की एक प्रति async() के कार्यान्वयन के भीतर कुछ बिंदु पर करने का प्रयास किया जाएगा के बाद से। इस समस्या को हल करने के लिए, आप std::ref() का उपयोग करके संदर्भ 0 में अपने task ऑब्जेक्ट को लपेटें।

+0

ग्रेट, धन्यवाद। यह काम करता है। लेकिन मैं कार्य को असंकालिक रूप से कैसे शुरू करूं? std :: async as (std :: launch :: async, task) अभी भी – rralf

+1

@rralf काम नहीं करता है: ऐसा इसलिए है क्योंकि (1) आप किसी ऑब्जेक्ट को घोषित कर रहे हैं, फ़ंक्शन को कॉल नहीं कर रहे हैं, और (2) अजीब अवरोधन के कारण जब आप लौटे भविष्य का उपयोग नहीं करते हैं तो 'async()' का व्यवहार। बस 'ऑटो एफ = async (...) 'करें। संपादित उत्तर देखें :) –

+0

मुझे लगता है कि अंतिम कोड ब्लॉक गलत है। 'As' से छुटकारा पाएं। – 0x499602D2

4

do_something() एक सदस्य कार्य है, जिसका अर्थ यह है कि यह पहले तर्क के रूप में एक अंतर्निहित this पॉइंटर लेता है। आपको bindthis पॉइंटर की आवश्यकता होगी, या एक लामाडा बनाएं जो do_something को आमंत्रित करता है।

foo() : 
    task(std::bind(&foo::do_something, this)), 
    result(task.get_future()) 
{} 

या

foo() : 
    task([this]{ return do_something(); }), 
    result(task.get_future()) 
{} 

std::async as(std::launch::async, task); 

std::async एक समारोह टेम्पलेट, नहीं एक प्रकार है। तो स्पष्ट परिवर्तन

std::async(std::launch::async, task); 

है लेकिन वह अभी तक एक और त्रुटि होती है क्योंकि इस बात का हिम्मत भीतर कहीं फोन task की एक प्रति का प्रयास किया है, लेकिन std::packaged_task किसी हटाए प्रतिलिपि निर्माता है। आप इसे std::ref का उपयोग कर ठीक कर सकते हैं, जो प्रतिलिपि से बच जाएगा।

std::async(std::launch::async, std::ref(task)); 
संबंधित मुद्दे