सामान्य विधि धागा हैंडल के सभी रखने के लिए और उसके बाद प्रत्येक हैंडल पर इंतजार है। जब हैंडल संकेतित किया गया है, तो धागा समाप्त हो गया है ताकि इसे धागे के सेट से हटा दिया जा सके। धागे हैंडल का ट्रैक रखने के लिए मैं std::set<HANDLE>
का उपयोग करता हूं। वहाँ Windows में एक से अधिक ऑब्जेक्ट पर इंतजार कर के लिए दो अलग-अलग तरीके हैं: सेट पर
- दोहराएं और हर एक
- पर एक समय समाप्ति के साथ
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
जैसे कुछ का उपयोग करने पर विचार करें।
यदि आपके पास केवल एक थ्रेड आईडी है, तो आपको इसे [ओपन थ्रेड] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335 (v = बनाम) पर कॉल करके पहले इसे हैंडल में परिवर्तित करना होगा। .85) .aspx)। – rustyx
नहीं, ओपन थ्रेड को कॉल न करें! यदि थ्रेड पहले ही बाहर निकला है और आईडी को फिर से सौंप दिया गया है, तो आप एक अलग हैंडल थ्रेड के लिए हैंडल के साथ समाप्त हो सकते हैं। _beginthreadex का प्रयोग करें, जो धागे को एक हैंडल देता है। (_beginthread भी एक हैंडल देता है, लेकिन (दस्तावेज़ों को उद्धृत करता है) यह "अमान्य हो सकता है या किसी अन्य धागे को इंगित कर सकता है"। _beginthread का कभी भी उपयोग न करें।) – benrg