WaitNamedPipe
फ़ंक्शन एक पाइप क्लाइंट एप्लिकेशन को नामित पाइप सर्वर पर उपलब्ध कनेक्शन के लिए सिंक्रनाइज़ रूप से प्रतीक्षा करने की अनुमति देता है। क्लाइंट के रूप में पाइप खोलने के लिए फिर आप CreateFile
पर कॉल करें। स्यूडोकोड:WaitNamedPipe के लिए एक ओवरलैप I/O विकल्प क्या है?
// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
if (WaitNamedPipe says connection is ready) {
hPipe = CreateFile(...);
if (hPipe ok or last error is NOT pipe busy) {
break; // hPipe is valid or last error is set
}
} else {
break; // WaitNamedPipe failed
}
}
समस्या यह है कि ये सभी अवरुद्ध, तुल्यकालिक कॉल हैं। यह असंकालिक रूप से करने का एक अच्छा तरीका क्या है? मुझे ऐसा एपीआई नहीं मिल रहा है जो ऐसा करने के लिए अतिव्यापी I/O का उपयोग करता है, उदाहरण के लिए। उदाहरण के लिए, पाइप सर्वरConnectNamedPipe
फ़ंक्शन के लिए lpOverlapped
पैरामीटर प्रदान करता है जो सर्वर को अतुल्यकालिक रूप से किसी ग्राहक के लिए प्रतीक्षा करने की अनुमति देता है। पाइप सर्वर तब WaitForMultipleObjects पर कॉल कर सकता है और I/O ऑपरेशन को पूरा करने के लिए प्रतीक्षा कर सकता है, या किसी अन्य घटना को संकेतित किया जा सकता है (उदाहरण के लिए, लंबित I/O को रद्द करने के लिए थ्रेड को सिग्नल करने वाला एक ईवेंट और समाप्त)।
एकमात्र तरीका मैं सोच सकता हूं कि WaitNamedPipe
को एक छोटे से, सीमित समय समाप्ति के साथ एक लूप में कॉल करें और यदि यह समय समाप्त हो तो अन्य संकेतों की जांच करें। वैकल्पिक रूप से, एक लूप कॉल CreateFile
पर, अन्य सिग्नल जांचें, और फिर Sleep
को छोटी देरी (या WaitNamedPipe
) पर कॉल करें। उदाहरण के लिए:
HANDLE hPipe;
while (true) {
hPipe = CreateFile(...);
if (hPipe not valid and pipe is busy) {
// sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
Sleep(100);
// TODO: check other signals here to see if we should abort I/O
} else
break;
}
लेकिन यह विधि मेरी राय में उच्च स्वर्ग तक जाती है। यदि थोड़ी देर के लिए एक पाइप उपलब्ध नहीं है, तो धागा चल रहा है - बिजली का उपयोग करके सीपीयू को चूसना, स्मृति पृष्ठों को राम में रहने की आवश्यकता है, आदि। मेरे दिमाग में, Sleep
या शॉर्ट टाइमआउट पर निर्भर धागा अच्छी तरह से प्रदर्शन नहीं करता है और मैला बहु-थ्रेडेड प्रोग्रामिंग का संकेत है।
लेकिन इस मामले में विकल्प क्या है?
एक स्पष्ट समाधान है कि कॉल को WaitNamedPipe को अलग थ्रेड में डालना है। आईआईआरसी, असीमित आईओ कार्यों में से कई वास्तव में हुड के नीचे थ्रेडिंग का उपयोग करते हैं, इसलिए यह उतना अक्षम नहीं है जितना लगता है। –
इस कोड द्वारा रेस की स्थिति के आसपास काम करने के बारे में हमें और बताएं। एमएस प्रलेखन नमूना क्लाइंट कोड पहले CreateFile को कॉल करने के लिए कहता है, और केवल पाइप व्यस्त के साथ विफल होने पर WaitNamedPipe को कॉल करें। प्रतीक्षा में उचित समय-आउट के साथ, इसे लूप में करें। यह हमेशा मेरे अनुभव में काम किया है। त्रुटि तब होती है जब दो क्लाइंट एक पाइप के लिए जाते हैं, लेकिन यह दौड़ नहीं है। एक ग्राहक जोड़ता है, और दूसरा इंतजार करता है और फिर कोशिश करता है जो आपके स्लीप उदाहरण के साथ होता है, लेकिन क्लीनर। –
@ मार्क: यह प्रलेखन में है। जब WaitNamedPipe सफल होता है, तो CreateFile अभी भी असफल हो सकता है क्योंकि दूसरा थ्रेड पहले कूद गया था। यह दौड़ की स्थिति है: पाइप खोलने के लिए दो या दो से अधिक धागे दौड़ रहे हैं। दौड़ की स्थिति के आसपास कामों में लूप डालना, इसलिए ओपीएस कोड में टिप्पणी। यह समस्या नहीं है कि वह हमें हल करने के लिए कह रहा है, हालांकि। –