2009-11-11 16 views
6

मेरे पास नीचे एक जैसा कार्यकर्ता वर्ग है:बूस्ट :: थ्रेडेड सदस्य फ़ंक्शन से वापसी मूल्य प्राप्त करना?

class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

इसका उद्देश्य boost :: thread और boost :: bind के साथ निष्पादित करना है, जैसे:

Worker worker; 
boost::function<int()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 

मेरा प्रश्न है, मैं कैसे कर सकता हूं वर्कर :: वापसी का मूल्य प्राप्त करें?

अग्रिम धन्यवाद।

उत्तर

7

मुझे नहीं लगता कि आप वापसी मूल्य प्राप्त कर सकते हैं।

इसके बजाय, आप कार्यकर्ता के सदस्य के रूप मान संग्रहीत कर सकते हैं:

class Worker{ 
public: 
    void Do(){ 
    int ret = 100; 
    // do stuff 
    m_ReturnValue = ret; 
    } 
    int m_ReturnValue; 
} 

और इसलिए की तरह उपयोग:

Worker worker; 
boost::function<void()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 
//do something with worker.m_ReturnValue 
+0

धन्यवाद मुझे लगता है कि मुझे थोड़ा सा डिज़ाइन करना होगा। –

2

इसके अलावा, आप भी कुछ अनावश्यक कॉल को बढ़ावा देने के लिए है :: बांध() और बढ़ावा :: समारोह()। क्योंकि थ्रेड के निर्माता एक आंतरिक बाँध() कॉल के चारों ओर एक सुविधा आवरण है

class Worker{ 
    public: 
     void operator(){ 
      int ret = 100; 
      // do stuff 
      m_ReturnValue = ret; 
     } 
    int m_ReturnValue; 
} 

Worker worker; 
boost::thread th(worker());//or boost::thread th(boost::ref(worker)); 

आप ऐसा कर सकते हैं: आप के बजाय निम्नलिखित कर सकते हैं। Thread Constructor with arguments

+0

यह काफी सरल दिखता है। धन्यवाद लेकिन मेरे वास्तविक कार्यान्वयन में कई सदस्य कार्य हैं, इसलिए मैं वास्तव में() ऑपरेटर का उपयोग नहीं कर सकता। –

+0

@ वह शिमिंग: आप अभी भी बाध्य() के बिना इसका उपयोग कर सकते हैं। उदाहरण के लिए, बूस्ट :: थ्रेड (वर्कर्स(), और वर्कर :: डू) (सिंटैक्स मेरे सिर के शीर्ष के बाद थोड़ा सा हो सकता है)। –

-2

दूसरा विकल्प Boost.Lambda लाइब्रेरी का उपयोग कर रहा है। तो फिर तुम कोड के रूप में Worker वर्ग बदले बिना इस प्रकार लिख सकते हैं:

Worker worker; 
int ret; 
boost::thread th(boost::lambda::var(ret) = worker.Do()); 
th.join(); 

यह विशेष रूप से उपयोगी है जब आप कॉल करने के लिए समारोह बदल नहीं सकते। इस तरह, वापसी मान स्थानीय चर ret में लपेटा गया है।

+4

यह मौजूदा थ्रेड में 'worker.Do()' निष्पादित करेगा, परिणाम को लैम्ब्डा ऑब्जेक्ट में कॉपी करें, उस थंबे को नए थ्रेड पर चलाएं (इस प्रकार 'कार्यकर्ता। डीओ() '' ret'' का परिणाम असाइन करें) और फिर नए धागे को पूरा करने के निष्पादन की प्रतीक्षा करें। यह संभवतः ** ** वांछित व्यवहार नहीं है, क्योंकि यह गलत थ्रेड में 'कार्यकर्ता।()' निष्पादित करता है। एक अलग थ्रेड में निष्पादित फ़ंक्शन से परिणाम प्राप्त करने का सबसे आसान तरीका वायदा और वादे का उपयोग करना है। – Mankarse

13

एक और विकल्प वादे/वायदा का उपयोग करना है।

class Worker{ 
public: 
    void Do(boost::promise<int> & p){ 
    int ret = 100; 
    // do stuff 
    p.set_value(ret); 
    } 
}; 
//Later... 
boost::promise<int> p; 
boost::thread t(boost::bind(&Worker::Do, &worker, boost::ref(p)); 
int retval = p.get_future().get(); //This will block until the promise is set. 

और अगर आप उपयोग कर सकते हैं C++ 0x, तो एसटीडी का उपयोग कर :: async ऊपर के सभी पैकेज होगा और बस कार्य करें:

std::future<int> f = std::async(std::bind(&Worker::Do, &worker)); 
int retval = f.get(); //Will block until do returns an int. 
1
class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

Worker worker; 
boost::packaged_task<int> ptask(boost::bind(&Worker::Do, &worker)); 
boost::unique_future<int> future_int = ptask.get_future(); 
boost::thread th(boost::move(ptask)); 
th.join(); 
if (future_int.is_ready()) 
    int return_value = future_int.get(); 

आप पर एक नज़र ले जा सकते हैं "बूस्ट :: भविष्य" अवधारणा, इस link