2010-08-13 15 views
8

क्या कोई विशिष्ट थ्रेड चलाने के लिए प्रतिनिधि प्राप्त करने का कोई तरीका है?एक विशिष्ट थ्रेड पर एक प्रतिनिधि को आमंत्रित करें C#

मेरे पास है कहते हैं:

CustomDelegate del = someObject.someFunction; 
Thread dedicatedThread = ThreadList[x]; 

मैं एक सुसंगत पृष्ठभूमि लंबी चलने वाली धागा है और जब भी मैं इसकी आवश्यकता है उस पर अपने ही प्रतिनिधियों आह्वान कर सकते हैं। यह हर बार एक ही धागा होना चाहिए।

[संपादित करें]

कारण है कि मैं इसे एक समर्पित धागे पर होना चाहता हूँ समय है कि मैं इस पर प्रतिनिधि को चलाने के लिए और y मिलीसेकेंड के बाद धागा स्थगित करता है, और फिर से शुरू धागा जब मैं चलाने के इरादे है इस पर एक और प्रतिनिधि। मुझे लगता है कि यह संभव नहीं है। मेरे पास एक प्रतिनिधि कतार होगी और धागे का मुख्य कार्य इसे पढ़ने और चलाने के लिए अनुमति देगा।

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

इस प्रकार एक समर्पित धागा है जिसमें मैं कई ईवेंट हैंडलर चला सकता हूं, अगर मैं बग हो गया या बहुत लंबा समय ले रहा हूं तो मैं किसी विशेष खिलाड़ी की एआई को रोक सकता हूं।

उत्तर

3

मुझे लगता है कि सबसे अच्छा समाधान Task ऑब्जेक्ट्स का उपयोग करना है और उन्हें StaThreadScheduler पर एक थ्रेड चलाने के लिए कतार देना है।

वैकल्पिक रूप से, आप Nito.Async में ActionThread का उपयोग Action प्रतिनिधियों की एक अंतर्निहित कतार के साथ एक सामान्य धागा बनाने के लिए कर सकता है।

हालांकि, इनमें से कोई भी सीधे किसी अन्य आवश्यकता को संबोधित नहीं करेगा: एक क्रिया को "रोकें" और किसी अन्य के साथ जारी रखने की क्षमता। ऐसा करने के लिए, आपको हर कार्रवाई में "सिंक्रनाइज़ेशन पॉइंट" छिड़कने की आवश्यकता होगी और इसके राज्य को सहेजने का एक तरीका होगा, इसे फिर से कतार दें, और अगली कार्रवाई के साथ जारी रखें।

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

+0

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

+0

चेतावनी का एक शब्द: यह संभव है (यहां तक ​​कि संभव है) थ्रेड को निलंबित/फिर से शुरू करके गलती से डेडलॉक्स का कारण बन सकता है। यदि संभव हो, तो बाहरी कोड बदलें। यदि यह संभव नहीं है, तो निलंबन/फिर से शुरू करने के बजाय थ्रेड प्राथमिकताओं का उपयोग करने पर विचार करें। –

1

आम तौर पर, मैं केवल थ्रेड पूल या BackgroundWorker कक्षा का उपयोग करने का सुझाव दूंगा - लेकिन ये गारंटी नहीं देते हैं कि काम किसी भी विशेष धागे पर होगा। यह स्पष्ट नहीं है तुम क्यों परवाह जो धागा काम करता है चलाता है, लेकिन यह सोचते हैं कि यह किसी भी तरह फर्क पड़ता है ...

आप एक कतार की तरह, साझा स्मृति के कुछ प्रकार के माध्यम से Delegate वस्तु पारित करने के लिए होगा। पृष्ठभूमि धागे को इस कतार को देखना होगा, जब वे मौजूद हों, तो प्रतिनिधियों को खींचें, और उन्हें निष्पादित करें।

यदि ऐसा पाया जाता है कि थ्रेड पूल अपने कोड को चलाने के लिए स्वीकार्य है, तो आप हमेशा BeginInvoke विधि प्रतिनिधि के ऐसा करने के लिए इस्तेमाल कर सकते हैं:

// wrap your custom delegate in an action for simplicity ... 
Action someCode =() => yourCustomDelegate(p1, p2, p3, ...); 
// asynchronously execute the currying Action delegate on the threadpool... 
someCode.BeginInvoke(someCode.EndInvoke, action); 
2
दुर्भाग्य से

वास्तव में बनाया गया कुछ भी नहीं यह करने के लिए है किसी भी सामान्य धागे पर। आप इसे एक वर्ग बनाने और इसे लागू करने वाले वर्ग को बनाकर पूरा कर सकते हैं ISynchonizeInvoke.

एलबीशकिन उल्लेख के रूप में समर्पित थ्रेड पर इवेंट प्रोसेसिंग कतार बनाने का एक सरल तरीका है। मैं Queue<Action> कक्षा का उपयोग करने और सीधे कार्य प्रतिनिधि को कॉल करने का सुझाव देता हूं। आप अज्ञात प्रतिनिधि कार्यों का उपयोग करके आवश्यक अधिकांश कार्यों को पूरा कर सकते हैं।

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

+0

धन्यवाद, मैं पृष्ठभूमि लूप को और अधिक चलाने का इरादा रख रहा था। मैं एक ईवेंट प्रतीक्षा हैंडलर – Raynos

+1

में देखूंगा, मैं 'थ्रेड स्लीप' के बारे में चेतावनी से सहमत हूं; हालांकि, ओप को पुराने 'ISynchronizeInvoke' के बजाय' सिंक्रनाइज़ेशन कॉन्टेक्स्ट 'लागू करना चाहिए। –

0

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

यह स्पष्ट नहीं है कि आप किस समस्या को हल करने की कोशिश कर रहे हैं। एक धागे पर एकाधिक प्रतिनिधियों को चलाने की कोशिश करके आप क्या पूरा करने (या टालना) करने की कोशिश कर रहे हैं?

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