2010-03-17 8 views
41

मैंने सी # में एक निर्माता/उपभोक्ता पैटर्न को लागू करने का प्रयास किया है। मेरे पास एक उपभोक्ता धागा है जो एक साझा कतार पर नजर रखता है, और एक उत्पादक थ्रेड जो साझा कतार पर आइटम रखता है। उत्पादक थ्रेड को डेटा प्राप्त करने के लिए सब्सक्राइब किया जाता है ... यानी, इसमें एक ईवेंट हैंडलर है, और बस आस-पास बैठता है और ऑनडाटा ईवेंट को आग लगने की प्रतीक्षा करता है (डेटा को किसी तृतीय पक्ष एपीआई से भेजा जा रहा है)। जब यह डेटा प्राप्त होता है, तो यह कतार पर चिपक जाता है ताकि उपभोक्ता इसे संभाल सके।.NET में, घटनाओं को किस धागे में संभाला जाएगा?

जब निर्माता में ऑनडाटा ईवेंट आग लगती है, तो मुझे उम्मीद है कि यह मेरे निर्माता धागे द्वारा संभाला जाएगा। लेकिन ऐसा नहीं लगता कि क्या हो रहा है। ऑनडाटा घटना ऐसा लगता है जैसे इसे नए धागे पर संभाला जा रहा है! क्या यह कैसे नेट हमेशा काम करता है ... घटनाओं को अपने धागे पर संभाला जाता है? क्या मैं नियंत्रित कर सकता हूं कि जब वे उठाए जाते हैं तो कौन सा धागा घटनाओं को संभालेगा? क्या होगा यदि सैकड़ों घटनाएं एक साथ-साथ उठाई जाएंगी ... क्या प्रत्येक का अपना धागा होगा?

+0

यह कुछ कोड, और/या कक्षाओं का उपयोग करने में आपकी सहायता कर सकता है। –

+0

क्या आप सी # 'घटना 'कीवर्ड भावनाओं, या' EventWaitHandle' अर्थ 'में घटनाओं के बारे में बात कर रहे हैं? मुझे लगता है कि आपको कुछ कोड पोस्ट करना चाहिए ... –

+0

@codeka: यह 'पोस्ट' जैसा लगता है, उसकी पोस्ट दी गई है। –

उत्तर

22

जब तक आप खुद को मार्शल नहीं करते हैं, तब भी कोई भी घटना जो भी थ्रेड इसे आक्रमण कर रही है, निष्पादित करेगी; घटनाओं के तरीके के बारे में कुछ भी खास नहीं है, और आपके निर्माता धागे में इवेंट हैंडलर नहीं है, आपके निर्माता धागे ने बस कहा "अरे, जब आप इस घटना को आग लगाते हैं, तो इस फ़ंक्शन को कॉल करें"। वहां कुछ भी नहीं है जो ईवेंट थ्रेड पर घटना निष्पादन का कारण बनता है, न ही अपने धागे पर (जब तक आप ईवेंट के प्रतिनिधि को सामान्य रूप से आमंत्रित करने के बजाय BeginInvoke का उपयोग नहीं करते थे, लेकिन यह इसे ThreadPool पर निष्पादित करेगा)।

74

प्रश्न को फिर से पढ़ने के बाद, मुझे लगता है कि अब मैं समस्या को समझता हूं। आपको मूल रूप से कुछ ऐसा मिला है:

class Producer 
{ 
    public Producer(ExternalSource src) 
    { 
     src.OnData += externalSource_OnData; 
    } 

    private void externalSource_OnData(object sender, ExternalSourceDataEventArgs e) 
    { 
     // put e.Data onto the queue 
    } 
} 

और फिर आपके पास एक उपभोक्ता धागा है जो उस कतार से सामान खींचता है। समस्या यह है कि ऑनडाटा ईवेंट को आपके ExternalSource ऑब्जेक्ट द्वारा निकाल दिया जाता है - जो भी थ्रेड चल रहा है, उस पर।

सी # event एस मूल रूप से प्रतिनिधियों का एक उपयोग में आसान संग्रह है और "फायरिंग" एक घटना सिर्फ रनटाइम को सभी प्रतिनिधियों के माध्यम से लूप करने का कारण बनती है और उन्हें एक समय में आग लगती है।

तो आपके ऑनडाटा ईवेंट हैंडलर को ExternalSource पर जो भी थ्रेड चल रहा है, पर कॉल किया जा रहा है।

+1

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

+13

@ बेन - आपको इसे स्वीकृत उत्तर के रूप में चिह्नित करना चाहिए। इससे दूसरों को उत्तर आसानी से देखने में मदद मिलेगी। –

+1

घटनाएं अलग-अलग होती हैं जब इनवॉक और BeginInvoke का उपयोग करके ईवेंट निकाल दिए जाते हैं..बिनगिनवोकोक घटना ग्राहक को थ्रेडपूल (पृष्ठभूमि थ्रेड में) से अलग थ्रेड में आमंत्रित करता है –

7

Invoke के साथ एक ईवेंट को बढ़ाना एक विधि को कॉल करने जैसा ही है - इसे उसी थ्रेड में निष्पादित किया जाता है जिसे आपने उठाया है।

BeginInvoke के साथ एक ईवेंट को बढ़ाने ThreadPool का उपयोग करता है। यहाँ कुछ minor details

-3

आप ..... इस समस्या के लिए autoresetevent संचालकों का उपयोग करने के autoresetevent में जब निर्माता produses यह संकेत सेट तो उपभोक्ता इसकी संकेत रीसेट और उपभोग राशि लेने वाली संकेत तो केवल निर्माता का उत्पादन सेट की खपत के बाद .. कर रहे हैं। ..

AutoResetEvent pro = new AutoResetEvent(false); 
AutoResetEvent con = new AutoResetEvent(true); 

public void produser() 
{ 

    while(true) 
    { 
     con.WaitOne(); 

     pro.Set(); 
    } 
} 

public void consumer() 
{ 
    while (true) 
    { 
    pro.WaitOne(); 
     .................**** 

    con.Set(); 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    Thread th1 = new Thread(produser); 
    th1.Start(); 
    Thread th2 = new Thread(consumer); 
    th2.Start(); 
} 
संबंधित मुद्दे