क्या एक ईवेंट लूप अनुकूलित मतदान के साथ सिर्फ / फॉर लूप है?


55

मैं समझने की कोशिश कर रहा हूं कि ईवेंट लूप क्या है। अक्सर स्पष्टीकरण यह होता है कि किसी ईवेंट लूप में, आप तब तक कुछ करते हैं जब तक आपको सूचित न कर दिया जाए कि कोई ईवेंट हुआ है। आप तब घटना को संभालते हैं और वही करते रहते हैं जो आप पहले कर रहे थे।

एक उदाहरण के साथ उपरोक्त परिभाषा को मैप करने के लिए। मेरे पास एक सर्वर है जो एक ईवेंट लूप में 'सुनता है', और जब एक सॉकेट कनेक्शन का पता लगाया जाता है, तो इससे प्राप्त डेटा को पढ़ा और प्रदर्शित किया जाता है, जिसके बाद सर्वर फिर से शुरू होता है / सुनने लगता है जैसा कि उसने पहले किया था।


हालाँकि, यह घटना हो रही है और हमें 'ठीक वैसे ही' नोटिफाई किया जा रहा है ताकि मुझे संभालना पड़े। आप कह सकते हैं: "यह उस तरह नहीं है जैसे कि 'आपको एक घटना श्रोता को पंजीकृत करना है"। लेकिन क्या एक घटना श्रोता है, लेकिन एक समारोह है जो किसी कारण के लिए वापस नहीं है। क्या यह स्वयं का लूप है, किसी घटना के होने पर अधिसूचित होने की प्रतीक्षा करना? क्या इवेंट श्रोता को भी इवेंट श्रोता को पंजीकृत करना चाहिए? यह कहाँ समाप्त होता है?


घटनाओं के साथ काम करने के लिए एक अच्छा अमूर्त है, लेकिन सिर्फ एक अमूर्त है। मेरा मानना ​​है कि अंत में, मतदान अपरिहार्य है। शायद हम इसे अपने कोड में नहीं कर रहे हैं, लेकिन निचले स्तर (प्रोग्रामिंग भाषा कार्यान्वयन या ओएस) हमारे लिए कर रहे हैं।

यह मूल रूप से निम्न छद्म कोड के लिए आता है जो कहीं कम चल रहा है, इसलिए यह व्यस्त प्रतीक्षा में परिणाम नहीं करता है:

while(True):
    do stuff
    check if event has happened (poll)
    do other stuff

यह पूरे विचार की मेरी समझ है, और मैं यह सुनना चाहूंगा कि क्या यह सही है। मैं यह स्वीकार करने में खुला हूं कि पूरा विचार मौलिक रूप से गलत है, इस मामले में मैं सही स्पष्टीकरण चाहूंगा।


3
इवेंट सिस्टम ऑब्जर्वर पैटर्न के कार्यान्वयन हैं । पैटर्न को समझना घटनाओं की आपकी समझ को सीमेंट करना चाहिए। किसी मतदान की आवश्यकता नहीं है।
स्टीवन एवर्स

1
अंतत: हां, भले ही भाषा उसे अलग करती हो।
ग्रैंडमास्टरबी

@SteveEvers आपकी विकि लिंक में। EventSourceयदि कीबोर्ड इनपुट पोल नहीं कर रहा है तो क्या कर रहा है?
TheMeaningfulEngineer

@ एलान: यह कुछ भी कर सकता है, लेकिन कीबोर्ड इनपुट के लिए विशेष रूप से मौजूद हैं एपीआई के रूप में आपके एप्लिकेशन को कीबोर्ड घटनाओं को सुनने के लिए पंजीकृत करने के लिए, जिसका उपयोग आप अपने इवेंट स्रोत के रूप में कर सकते हैं जिसमें कोई मतदान शामिल नहीं है। बेशक, यदि आप काफी नीचे जाते हैं, तो USB हमेशा मतदान करता है, लेकिन मान लें कि हम PS / 2 कीबोर्ड का उपयोग कर रहे हैं, जो बाधित है, और फिर आपके पास शून्य मतदान के साथ घटनाओं के आधार पर एक कीबोर्ड इनपुट स्टैक है।
फॉशी

मेरे पास यह प्रश्न वर्षों से है, लेकिन मैं यह नहीं बता सकता कि मैंने इसे पूछने की जहमत क्यों उठाई। धन्यवाद, मैं अब समझ से संतुष्ट हूं @ कार्ल बेलेफेल्ट ने मुझे समझ लिया है।
0xc0de

जवाबों:


54

यदि कोई ईवेंट तैयार नहीं होता है, तो अधिकांश ईवेंट लूप सस्पेंड कर देगा, जिसका अर्थ है कि ऑपरेटिंग सिस्टम किसी भी घटना के होने तक कार्य को किसी भी निष्पादन समय नहीं देगा।

कहो कि घटना को दबाया जा रहा है। आप पूछ सकते हैं कि क्या कीपर्स के लिए ऑपरेटिंग सिस्टम की जाँच में कहीं लूप है। जवाब न है। कुंजी दबाए जाने से एक अवरोध उत्पन्न होता है , जिसे हार्डवेयर द्वारा अतुल्यकालिक रूप से नियंत्रित किया जाता है। इसी तरह टाइमर, माउस मूवमेंट, एक पैकेट आने आदि के लिए।

वास्तव में, अधिकांश ऑपरेटिंग सिस्टम के लिए, घटनाओं के लिए मतदान अमूर्त है। हार्डवेयर और OS, एसिंक्रोनस रूप से घटनाओं को संभालते हैं और उन्हें एक कतार में डालते हैं जो अनुप्रयोगों द्वारा मतदान किया जा सकता है। आप वास्तव में एम्बेडेड सिस्टम में केवल हार्डवेयर स्तर पर सही मतदान देखते हैं, और यहां तक ​​कि हमेशा नहीं।


4
क्या एक तार पर वोल्टेज का एक व्यवधान नहीं है? क्या वह स्वयं किसी घटना को ट्रिगर कर सकता है या हमें वोल्टेज मान के लिए पिन को प्रदूषित करना चाहिए?
TheMeaningfulEngineer

8
जो अपने आप किसी घटना को ट्रिगर कर सकता है। प्रोसेसर को इस तरह से डिज़ाइन किया गया है। वास्तव में एक प्रोसेसर को एक रुकावट से नींद से जगाया जा सकता है।
कार्ल बेवेलफेल्ट

2
मैं बयान से भ्रमित हूं Most event loops will block। यह "इवेंट लूप प्रतिमान में कैसे फिट बैठता है, थ्रेड का उपयोग करने के विरोध में, गैर-समरूप एसिंक्रोनस कॉल का उपयोग करता है"?
द मेनिंगफुल एंजिनियर

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

1
मुझे लगता है कि आप इसे इस तरह से देख सकते हैं, लेकिन यह एप्लिकेशन कोड के बजाय लाइब्रेरी और / या ओएस में मल्टी थ्रेडिंग है। इवेंट लूप्स एप्लिकेशन डेवलपर के लिए सिंक्रनाइज़ेशन समस्याओं को दूर करता है।
कार्ल बेजेलफेल्ट

13

मुझे लगता है कि एक इवेंट श्रोता एक फंक्शन के रूप में नहीं बल्कि अपना खुद का लूप चला रहा है, लेकिन पहली दौड़ के साथ एक रिले रेस के रूप में। मतदान के बजाय घटनाओं का उपयोग करने का एक महत्वपूर्ण कारण यह है कि वे सीपीयू चक्रों के साथ अधिक कुशल हैं। क्यों? इसे हार्डवेयर अप से देखें (स्रोत कोड डाउन होने के बजाय)।

एक वेब सर्वर पर विचार करें। जब आपका सर्वर कॉल listen()और ब्लॉक करता है, तो आपका कोड रिले रनर के रूप में अपनी जगह ले रहा है। जब एक नया कनेक्शन का पहला पैकेट आता है, तो नेटवर्क कार्ड ऑपरेटिंग सिस्टम को बाधित करके दौड़ शुरू करता है। ओएस एक इंटरप्ट सर्विस रूटीन (ISR) चलाता है जो पैकेट को पकड़ता है। ISR एक उच्च-स्तरीय दिनचर्या के लिए बैटन को पास करता है जो कनेक्शन स्थापित करता है। एक बार कनेक्शन जीवित हो जाने के बाद, वह रूटीन बैटन पास करता है listen(), जो आपके कोड तक बैटन को पास करता है। उस बिंदु पर, आप कनेक्शन के साथ जो चाहें कर सकते हैं। सभी के लिए हम जानते हैं, दौड़ के बीच प्रत्येक रिले धावक पब में जा सकता है। घटना अमूर्तता की एक ताकत यह है कि आपके कोड को जानने या देखभाल करने की आवश्यकता नहीं है।

कुछ ऑपरेटिंग सिस्टम में इवेंट-हैंडलिंग कोड शामिल होता है जो दौड़ के अपने हिस्से को चलाता है, बैटन से हाथ हटाता है, फिर अगली दौड़ शुरू होने की प्रतीक्षा करने के लिए अपने शुरुआती बिंदु पर वापस आ जाता है। इस अर्थ में, समवर्ती छोरों के बहुत से ईवेंट हैंडलिंग को पोलिंग अनुकूलित किया गया है। हालांकि, हमेशा एक बाहरी ट्रिगर होता है जो प्रक्रिया को बंद कर देता है। ईवेंट श्रोता एक ऐसा फ़ंक्शन नहीं है जो वापस नहीं आ रहा है, लेकिन एक फ़ंक्शन जो उस बाहरी ट्रिगर की प्रतीक्षा कर रहा है इससे पहले कि वह चलता है। बजाय:

while(True):
    do stuff
    check if event has happened (poll)
    do other stuff

मैं इसके बारे में सोचता हूं:

on(some event):    //I got the baton
     do stuff
     signal the next level up    //Pass the baton

और signalअगली बार जब हैंडलर चलता है, तो वैचारिक रूप से कोई कोड रनिंग या लूपिंग नहीं होता है।


यह समझ में आता है, हालांकि जब यह रुकावट की प्रतीक्षा कर रहा है तो इवेंट लूप क्या कर रहा है? यदि यह अवरुद्ध है, तो क्या यह 'बहु थ्रेडेड' अप्रोच नहीं है, जो ईवेंट लूप के विपरीत है?
सुंदर अंगरक्षक

यदि आपके कोड में लूप है forever: { select(); do stuff; }तो आप लूप के माध्यम से हर बार रेस में पुनः प्रवेश कर रहे हैं। चाहे आप एक ही धागे से या अलग-अलग धागे या प्रोसेसर पर समानांतर रूप से बार-बार करते हों, मैं प्रत्येक घटना को अपनी जाति मानता हूं। उदाहरण के लिए, एक वेब ब्राउज़र एक मल्टीथ्रेडेड प्रोग्राम है जिसमें कई थ्रेड्स अलग-अलग थ्रेड्स में होते हैं, कम से कम यूआई के लिए एक और प्रत्येक पेज जो इसे डाउनलोड कर रहा है। प्रश्न जब मैं पूछता हूं कि कोडिंग "मैं घटनाओं को तेजी से कैसे संसाधित कर सकता हूं?" कभी-कभी जवाब एक लूप होता है, कभी-कभी थ्रेड्स, अक्सर एक संयोजन।
cxw

मैं एक-दो दशकों से अधिक समय से इवेंट-आधारित प्रोग्रामिंग कर रहा हूं, और मुझे यह उत्तर बहुत भ्रमित करने वाला लगा। एक श्रोता को काम करने के लिए, एक लूप होना चाहिए जो किसी घटना की प्रतीक्षा करता है, फिर सभी पंजीकृत श्रोताओं के लिए इसे रूट करता है। (मान लें कि हम हार्डवेयर इंटरप्ट के बजाय सॉफ़्टवेयर के बारे में बात कर रहे हैं)
ब्रायन ओकले

8

नहीं। यह "अनुकूलित मतदान नहीं है।" एक ईवेंट-लूप मतदान के बजाय बाधित-संचालित I / O का उपयोग करता है।

जबकि, जब तक, के लिए, आदि लूप पोलिंग लूप हैं।

"मतदान" कुछ को बार-बार जाँचने की प्रक्रिया है। चूंकि लूप कोड लगातार निष्पादित होता है, और क्योंकि यह एक छोटा, "तंग" लूप है, प्रोसेसर को कार्यों को स्विच करने और कुछ भी करने के लिए बहुत कम समय है। लगभग सभी "हैंग," "जमा देता है," "लॉकअप" या जो कुछ भी आप इसे कॉल करना चाहते हैं जब कंप्यूटर अनुत्तरदायी हो जाता है, तो एक अनपेक्षित मतदान लूप में कोड के प्रकट होने की अभिव्यक्ति होती है। इंस्ट्रूमेंटेशन 100% सीपीयू उपयोग दिखाएगा।

इंटरप्ट-चालित ईवेंट लूप पोलिंग लूप की तुलना में कहीं अधिक कुशल हैं। मतदान सीपीयू चक्रों का एक अत्यंत बेकार उपयोग है इसलिए इसे खत्म करने या कम करने के लिए हर संभव प्रयास किया जाता है।

हालाँकि, कोड गुणवत्ता को अनुकूलित करने के लिए, अधिकांश भाषाएं मतदान लूप प्रतिमान का उपयोग करने की कोशिश करती हैं, क्योंकि वे किसी प्रोग्राम के भीतर कार्यात्मक रूप से समान उद्देश्यों की पूर्ति के लिए इवेंट हैंडिंग कमांड के लिए जितना संभव हो सके। इस प्रकार, एक कुंजी या किसी चीज़ के लिए प्रतीक्षा करने के लिए अधिक परिचित तरीके से मतदान करने के साथ, अनुभवहीन के लिए इसका उपयोग करना आसान है और एक प्रोग्राम के साथ हवा देना जो स्वयं ठीक हो सकता है, लेकिन इसके चलने पर कुछ और काम नहीं करता है। यह मशीन पर "ले" गया है।

जैसा कि अन्य उत्तरों में समझाया गया है, बाधित-चालित ईवेंट हैंडिंग में, अनिवार्य रूप से एक "ध्वज" सीपीयू के भीतर सेट किया गया है और प्रक्रिया को "निलंबित" (चलाने की अनुमति नहीं है) जब तक कि झंडा किसी अन्य प्रक्रिया से बदल न जाए (जैसे कीबोर्ड ड्राइवर बदल रहा है जब उपयोगकर्ता ने एक कुंजी दबाया है)। यदि ध्वज एक वास्तविक हार्डवेयर स्थिति है जैसे कि एक रेखा "उच्च खींची जा रही है," इसे "रुकावट" या "हार्डवेयर व्यवधान" कहा जाता है। हालाँकि, ज्यादातर CPU या मुख्य मेमोरी (RAM) में एक मेमोरी एड्रेस के रूप में लागू किया जाता है और इसे "सेमाफोर" कहा जाता है।

सॉफ्टवेयर नियंत्रण के तहत सेमाफोरस को बदला जा सकता है और इसलिए सॉफ्टवेयर प्रक्रियाओं के बीच एक बहुत तेज, सरल सिग्नलिंग तंत्र प्रदान कर सकता है।

इंटरप्ट, हालांकि, केवल हार्डवेयर द्वारा बदला जा सकता है। इंटरप्ट का सबसे सर्वव्यापी उपयोग आंतरिक क्लॉक चिप द्वारा नियमित अंतराल पर ट्रिगर किया गया है। घड़ी के अवरोधों द्वारा सक्रिय सॉफ्टवेयर क्रियाओं के अनगिनत प्रकारों में से एक है, सेमाफोरस का बदलना।

मैंने बहुत कुछ छोड़ दिया है, लेकिन कहीं रुकना पड़ा। कृपया पूछें कि क्या आपको अधिक जानकारी चाहिए।


7

आमतौर पर इसका उत्तर हार्डवेयर होता है, ओएस और बैकग्राउंड थ्रेड्स जो आपको नियंत्रित नहीं करते हैं, यह आसान नहीं लगता है। नेटवर्क कार्ड कुछ डेटा प्राप्त करता है जो सीपीयू को बताने के लिए एक बाधा उत्पन्न करता है। OS का इंटरप्ट हैंडलर इसे संभालता है। तब एक पृष्ठभूमि धागा जिसे आप नियंत्रित नहीं करते हैं (जो कि ईवेंट के लिए पंजीकरण करके बनाया गया था और जब से आप इस घटना के लिए पंजीकृत हुए हैं तब से सो रहा है) ओएस द्वारा घटना को संभालने के भाग के रूप में जगाया गया है और आपके ईवेंट हैंडलर को चलाता है।


7

मैं अब तक देखे गए अन्य सभी उत्तरों के खिलाफ जा रहा हूं और "हां" कहूंगा । मुझे लगता है कि अन्य उत्तर चीजों को बहुत जटिल कर रहे हैं। एक वैचारिक दृष्टिकोण से, सभी ईवेंट लूप अनिवार्य रूप से हैं:

while <the_program_is_running> {
    event=wait_for_next_event()
    process_event(event)
}

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


1
सीधा होने के लिए +1। लेकिन जोर "प्रतीक्षा" पर है; इस कोड का निष्पादन लूप की पहली पंक्ति पर रोक देगा और किसी घटना के होने तक जारी नहीं रहेगा। यह एक व्यस्त पोलिंग लूप से अलग है जो किसी घटना के होने तक बार-बार चेक करता है।
टॉम पैनिंग

1

सभी घटनाओं के ट्रिगर को छोरों में नहीं संभाला जाता है। जिस तरह से मैं अक्सर अपने खुद के ईवेंट इंजन लिखता हूं वह इस तरह होगा:

interface Listener {
    void handle (EventInfo info);
}

List<Listener> registeredListeners

void triggerEvent (EventInfo info) {
    foreach (listener in registeredListeners) { // Memo 1
        listener.handle(info) // the handling may or may not be synchronous... your choice
    }
}

void somethingThatTriggersAnEvent () {
    blah
    blah
    blah
    triggerEvent(someGeneratedEventInfo)
    more blah
}

ध्यान दें कि हालांकि मेमो 1 एक लूप पर है, लूप प्रत्येक श्रोता को सूचित करने के लिए है। जरूरी नहीं कि इवेंट ट्रिगर ही लूप में हो।

सिद्धांत रूप में, ओएस-स्तर की प्रमुख घटनाएं एक ही तकनीक का उपयोग कर सकती हैं (हालांकि मुझे लगता है कि वे अक्सर इसके बजाय मतदान करते हैं? मैं यहां सिर्फ अनुमान लगा रहा हूं), बशर्ते ओएस कुछ प्रकार के registerListenerएपीआई को उजागर करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.