2010-07-05 10 views
5

मैं _beginthread साथ अपने आवेदन में multithreading का उपयोग कर रहा हूँ और अभी इंतजार करना जब तक सभी धागे से किया जाता है मैं वैश्विक bools यह सच करने के लिए तैयार हो जाओ के रूप में प्रत्येक धागा पूरा करता है तो मैं तब तक थोड़ी देर के पाश में हूँ है। ऐसा करने का एक साफ तरीका होना चाहिए?धागे किए जाने पर जांचने का सही तरीका?

धन्यवाद

उत्तर

8

आप WaitForMultipleObjects उपयोग कर सकते हैं धागे प्राथमिक सूत्र में समाप्त होने की प्रतीक्षा करने के लिए।

+0

यदि आपके पास केवल एक थ्रेड आईडी है, तो आपको इसे [ओपन थ्रेड] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335 (v = बनाम) पर कॉल करके पहले इसे हैंडल में परिवर्तित करना होगा। .85) .aspx)। – rustyx

+2

नहीं, ओपन थ्रेड को कॉल न करें! यदि थ्रेड पहले ही बाहर निकला है और आईडी को फिर से सौंप दिया गया है, तो आप एक अलग हैंडल थ्रेड के लिए हैंडल के साथ समाप्त हो सकते हैं। _beginthreadex का प्रयोग करें, जो धागे को एक हैंडल देता है। (_beginthread भी एक हैंडल देता है, लेकिन (दस्तावेज़ों को उद्धृत करता है) यह "अमान्य हो सकता है या किसी अन्य धागे को इंगित कर सकता है"। _beginthread का कभी भी उपयोग न करें।) – benrg

3

आप धागा तुल्यकालन तकनीक है पर एक नजर है करने के लिए क्या चाहते हैं - सौभाग्य से वहाँ MSDN पर जानकारी का काफ़ी जो शायद आपकी सहायता कर सकते हैं। यह संभावना है कि आप एमएसडीएन पर मुख्य सामग्री इवेंट्स और वेटहैंडल्स का उपयोग करना चाहेंगे: http://msdn.microsoft.com/en-us/library/ms681924%28v=VS.85%29.aspx कई उदाहरण हैं।

वहाँ भी MFC में तुल्यकालन पर कुछ जानकारी (जो या मददगार साबित नहीं हो सकता है, संदर्भ उद्देश्यों के लिए जोड़ा गया) है: http://msdn.microsoft.com/en-us/library/975t8ks0%28VS.71%29.aspx

मैं खोज का एक सा किया है, लेकिन मैं एक कठिन समय की कोशिश कर लिया है आपके लिए कुछ उपयोगी जानकारी ट्रैक करने के लिए जो एमएफसी कार्यान्वयन का उपयोग नहीं करता है। यहां एक अच्छा ट्यूटोरियल है (http://www.informit.com/library/content.aspx?b=Visual_C_PlusPlus&seqNum=149) लेकिन, फिर से, एमएफसी का उपयोग कर। शुरुआत के रूप में आप mutexes के एमएफसी कार्यान्वयन पर एक नज़र डाल सकते हैं।

तो, आप तुल्यकालन कार्य करता है और संरचनाओं से परिचित प्राप्त करने की आवश्यकता होगी - सभी MSDN पर यहां शामिल: http://msdn.microsoft.com/en-us/library/ms686679%28v=VS.85%29.aspx

+0

आपको निश्चित रूप से बूल पर घटनाओं का उपयोग करने की आवश्यकता है। – DanDan

2

उपयोग _beginthreadex बजाय। दोनों _beginthread और _beginthreadexreturn a thread handle, लेकिन धागा शुरू कर दिया साथ _beginthread स्वचालित रूप से इसके हैंडल बंद कर देता है जब यह खत्म, इसलिए तुल्यकालन के लिए उपयोग विश्वसनीय नहीं है।

थ्रेड हैंडल Win32 के सिंक्रनाइज़ेशन फ़ंक्शंस में से एक के साथ उपयोग किया जा सकता है, जैसे WaitForSingleObject या WaitForMultipleObjects

पूर्ण होने पर, _beginthreadex द्वारा दिया हैंडल CloseHandle() साथ बंद होना चाहिए।

0

विंडोज एक और सूचित करने के लिए एक थ्रेड के लिए घटनाओं प्रदान करता है। बॉक्स के बाहर विजुअल सी ++ केवल एमएफसी के अंदर घटनाओं के लिए समर्थन प्रदान करता है। पोर्टेबल, गैर-एमएफसी संस्करण के लिए, बूस्ट लाइब्रेरी के thread management classes देखें। वे थ्रेड को लॉन्च करने और प्रतीक्षा करने के लिए बहुत आसान बनाते हैं, हालांकि वे सभी विंडोज एपीआई की कार्यक्षमता तक सीधे पहुंच प्रदान नहीं करते हैं।

1

सामान्य विधि धागा हैंडल के सभी रखने के लिए और उसके बाद प्रत्येक हैंडल पर इंतजार है। जब हैंडल संकेतित किया गया है, तो धागा समाप्त हो गया है ताकि इसे धागे के सेट से हटा दिया जा सके। धागे हैंडल का ट्रैक रखने के लिए मैं std::set<HANDLE> का उपयोग करता हूं। वहाँ Windows में एक से अधिक ऑब्जेक्ट पर इंतजार कर के लिए दो अलग-अलग तरीके हैं: सेट पर

  1. दोहराएं और हर एक
  2. पर एक समय समाप्ति के साथ WaitForSingleObject फोन किसी सरणी या वेक्टर में सेट कन्वर्ट और फोन WaitForMultipleObjects

पहली बार अक्षम लगता है, लेकिन यह वास्तव में दोनों का सबसे प्रत्यक्ष और कम से कम त्रुटि प्रवण है।

std::set<HANDLE> thread_handles; // contains the handle of each worker thread 
while (!thread_handles.empty()) { 
    std::set<HANDLE> threads_left; 
    for (std::set<HANDLE>::iterator cur_thread=thread_handles.begin(), 
            last=thread_handles.end(); 
     cur_thread != last; ++cur_thread) 
    { 
     DWORD rc = ::WaitForSingleObject(*cur_thread, some_timeout); 
     if (rc == WAIT_OBJECT_0) { 
      ::CloseHandle(*cur_thread); // necessary with _beginthreadex 
     } else if (rc == WAIT_TIMEOUT) { 
      threads_left.add(cur_thread); // wait again 
     } else { 
      // this shouldn't happen... try to close the handle and hope 
      // for the best! 
      ::CloseHandle(*cur_thread); // necessary with _beginthreadex 
     } 
    } 
    std::swap(threads_left, thread_handles); 
} 

WaitForMultipleObjects का उपयोग करते हुए समाप्त करने के लिए सूत्र के लिए प्रतीक्षा करने के लिए थोड़ा और अधिक मुश्किल से यह लग रहा है: आप, धागे के सभी के लिए प्रतीक्षा करने की जरूरत है उसके बाद निम्न पाश का उपयोग करें। निम्नलिखित सभी धागे के लिए इंतजार करेंगे; तथापि, यह एक बार में केवल WAIT_MAXIMUM_OBJECTS धागे के लिए इंतजार कर रहा है। एक और विकल्प धागे के प्रत्येक पृष्ठ पर लूप करना है। मैं उस अभ्यास को पाठक को छोड़ दूंगा;)

DWORD large_timeout = (5 * 60 * 1000); // five minutes 
std::set<HANDLE> thread_handles; // contains the handle of each worker thread 
std::vector<HANDLE> ary;   // WaitForMultipleObjects wants an array... 
while (!thread_handles.empty()) { 
    ary.assign(thread_handles.begin(), thread_handles.end()); 
    DWORD rc = ::WaitForMultipleObjects(std::min(ary.size(), WAIT_MAXIMUM_OBJECTS), 
             &ary[0], FALSE, large_timeout); 
    if (rc == WAIT_FAILED) { 
     // handle a failure case... this is usually something pretty bad 
     break; 
    } else if (rc == WAIT_TIMEOUT) { 
     // no thread exited in five minutes... this can be tricky since one of 
     // the threads beyond the first WAIT_MAXIMUM_OBJECTS may have terminated 
    } else { 
     long idx = (rc - WAIT_OBJECT_0); 
     if (idx > 0 && idx < ary.size()) { 
      // the object at `idx` was signaled, this means that the 
      // thread has terminated. 
      thread_handles.erase(ary[idx]); 
      ::CloseHandle(ary[idx]); // necessary with _beginthreadex 
     } 
    } 
} 

यह बिल्कुल सुंदर नहीं है लेकिन इसे काम करना चाहिए। तुम पर भरोसा है कि आपके धागे के सभी बाहर निकल जाएगा और उनके लिए इंतज़ार कोई आपत्ति नहीं है, तो आप WaitForMultipleObjects(ary.size(), &ary[0], TRUE, INFINITE) उपयोग कर सकते हैं। यह आमतौर पर बहुत ही सुरक्षित है, हालांकि अनिश्चित काल के लिए ब्लॉक करने के लिए अपने आवेदन के बाद से एक भगोड़ा धागा कारण होगा और यह केवल यदि ary.size()MAXIMUM_WAIT_OBJECTS तुलना में कम है काम करेंगे नहीं है।

बेशक अन्य विकल्प के लिए एक थ्रेड पूल कार्यान्वयन खोजने के लिए और उसका उपयोग करना चाहते है। लेखन थ्रेडिंग कोड वास्तव में बहुत मजेदार नहीं है, खासकर जब आप इसे जंगली में समर्थन देना चाहते हैं। इसके बजाय boost::thread_group जैसे कुछ का उपयोग करने पर विचार करें।

0

आप को बढ़ावा देने :: धागा वस्तुओं का उपयोग कर सकते हैं। वस्तु पर join कॉल और धागा समाप्त करने के लिए के लिए यह इंतजार करेंगे।

संबंधित मुद्दे