2012-03-26 13 views
5

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 या शॉर्ट टाइमआउट पर निर्भर धागा अच्छी तरह से प्रदर्शन नहीं करता है और मैला बहु-थ्रेडेड प्रोग्रामिंग का संकेत है।

लेकिन इस मामले में विकल्प क्या है?

+1

एक स्पष्ट समाधान है कि कॉल को WaitNamedPipe को अलग थ्रेड में डालना है। आईआईआरसी, असीमित आईओ कार्यों में से कई वास्तव में हुड के नीचे थ्रेडिंग का उपयोग करते हैं, इसलिए यह उतना अक्षम नहीं है जितना लगता है। –

+0

इस कोड द्वारा रेस की स्थिति के आसपास काम करने के बारे में हमें और बताएं। एमएस प्रलेखन नमूना क्लाइंट कोड पहले CreateFile को कॉल करने के लिए कहता है, और केवल पाइप व्यस्त के साथ विफल होने पर WaitNamedPipe को कॉल करें। प्रतीक्षा में उचित समय-आउट के साथ, इसे लूप में करें। यह हमेशा मेरे अनुभव में काम किया है। त्रुटि तब होती है जब दो क्लाइंट एक पाइप के लिए जाते हैं, लेकिन यह दौड़ नहीं है। एक ग्राहक जोड़ता है, और दूसरा इंतजार करता है और फिर कोशिश करता है जो आपके स्लीप उदाहरण के साथ होता है, लेकिन क्लीनर। –

+1

@ मार्क: यह प्रलेखन में है। जब WaitNamedPipe सफल होता है, तो CreateFile अभी भी असफल हो सकता है क्योंकि दूसरा थ्रेड पहले कूद गया था। यह दौड़ की स्थिति है: पाइप खोलने के लिए दो या दो से अधिक धागे दौड़ रहे हैं। दौड़ की स्थिति के आसपास कामों में लूप डालना, इसलिए ओपीएस कोड में टिप्पणी। यह समस्या नहीं है कि वह हमें हल करने के लिए कह रहा है, हालांकि। –

उत्तर

4

WaitNamedPipe पूरी तरह से बेकार है, और यदि आप टाइमआउट निर्दिष्ट करते हैं तो बस सभी सीपीयू का उपयोग करेंगे और इसके लिए कोई सर्वर इंतजार नहीं कर रहा है।

Sleep के साथ बस CreateFile पर कॉल करें जैसे आप कर रहे हैं, और इसे उचित रूप से देखते हुए इसे अन्य थ्रेड पर ले जाएं। कोई एपीआई विकल्प नहीं है।

केवल "लाभ" WaitNamedPipe प्रदान करता है अगर आप जानना चाहते हैं कि क्या आप किसी नामित पाइप से कनेक्ट कर सकते हैं लेकिन आप स्पष्ट रूप से कनेक्शन खोलना नहीं चाहते हैं। यह जंक है।

तुम सच में पूरी तरह से करना चाहते हैं, अपने ही विकल्प

  • सुनिश्चित करें जो कुछ भी कार्यक्रम है खोलने नामित पाइप हमेशा CreateNamedPipe फिर तुरंत बाद यह पाइप नामक बुला रहा है कि से जुड़ा है कर रहे हैं।
  • क्या आपका प्रोग्राम वास्तव में जांचता है कि वह प्रोग्राम चल रहा है या नहीं।
  • यदि आपके इरादे में वास्तव में अतिरिक्त कनेक्शन नहीं हैं, तो अभी भी CreateNamedPipe पर कॉल करें, और जब कोई कनेक्ट होता है, तो उन्हें तब तक जाने के लिए कहें जब तक कि वे एक निश्चित समय तक प्रतीक्षा न करें, पाइप बंद करें।
+0

मुझे अनुमान है कि यह केवल सभी सीपीयू का उपयोग करता है यदि कुछ और प्रतिस्पर्धा नहीं कर रहा है? प्रति घड़ी टिक एक बार कम से कम सीपीयू पैदा करना चाहिए। यह वास्तव में समझ में आता है - इसका मतलब है कि अंतर्निहित प्रोटोकॉल कनेक्शन को कतारबद्ध करने का कोई तरीका नहीं प्रदान करता है, जो बताता है कि एसिंक संस्करण क्यों नहीं है। टीसीपी कनेक्शन के साथ यह वही है। अगर सर्वर का अंत नहीं सुन रहा है, तो कहने का कोई तरीका नहीं है "ओह, ठीक है, मुझे मुफ्त में वापस कॉल करें", आपको केवल समय-समय पर पुनः प्रयास करना होगा। –

+0

यह माइक्रोसॉफ्ट द्वारा सिर्फ उपेक्षा है। जब आप टाइमआउट के साथ 'WaitNamedPipe' को कॉल करते हैं, तो आपके सीपीयू में से एक तब तक 100% पर होगा जब तक कि यह रिटर्न न हो - इसे एक livelock कहा जाता है - अन्य चीजों को चलाने की अनुमति दी जाएगी, लेकिन उस सीपीयू पर कोई निष्क्रिय चक्र नहीं होगा। मुझे संदेह है कि वे इसे एक या दो दशक के भीतर उपाय करेंगे। – fcrick

+0

मैं बस एक सीमित टाइमआउट का उपयोग कर घायल हो गया। –

2

सर्वर क्यों अधिक पाइप बना सकता है? आपके द्वारा वर्णित परिदृश्य में प्रदर्शन हिट होने पर कोई समस्या नहीं है।

आईई। यदि आमतौर पर WaitForMultipleObjects के बजाय CreateFile/Sleep का उपयोग करते हैं तो क्या यह महत्वपूर्ण है कि क्या गोल करने के लिए पर्याप्त पाइप हैं? प्रदर्शन हिट कोई फर्क नहीं पड़ता।

मुझे क्लाइंट में ओवरलैप किए गए आईओ की आवश्यकता पर भी सवाल उठाना होगा। यह एक समय में कितने सर्वर संचार कर रहा है? अगर उत्तर से कम है, तो कहें, 10 आप उचित रूप से प्रति कनेक्शन धागा बना सकते हैं।

असल में मैं कह रहा हूं कि मुझे लगता है कि WaitforNamedPipe कोई ओवरलैप्ड नहीं है क्योंकि इसका कोई उचित उपयोग-मामला नहीं है जिसके लिए इसकी आवश्यकता है।

+0

ग्राहकों के पास सर्वर पर नियंत्रण नहीं है, और सबसे खराब मानने की आवश्यकता है। (इस विशेष मामले में, सर्वर केवल एक समय में एक क्लाइंट को संभालता है, लेकिन मुझे लगता है कि एक सर्वर ने एक समय में कई क्लाइंटों को संभाला है, फिर भी क्लाइंट को पूर्ण सर्वर के लिए तैयार होना चाहिए।) –

+0

@ जेम्स जेम्सस्टन: क्या आप नहीं लिख रहे हैं सर्वर कोड? नामित पाइप का उपयोग ज्यादातर ग्राहकों और सर्वरों द्वारा एक साथ लिखा जाता है। –

+0

@Ben उपयोग केस जिसके लिए WaitNamedPipe का ओवरलैप्ड IO संस्करण आवश्यक है, जहां क्लाइंट प्रतीक्षा करते समय कुछ करना चाहता है, लेकिन प्रतीक्षा को अपने थ्रेड में रखना एक विकल्प नहीं है। यह शायद ही असामान्य उपयोग का मामला है! –

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