2009-06-24 14 views
7

मैं प्लग-इन मॉडल का एक तरहबनाना नियंत्रण धागा

Activator.CreateInstanceFrom(dllpath, classname). 

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

यह ठीक काम करता प्रतीत होता है - जब तक कि मैं इन उपयोगकर्ता नियंत्रणों में से किसी एक पर किसी नेस्टेड नियंत्रण पर कोई भी संपत्ति सेट करने का प्रयास नहीं करता, उदा। एक बटन के ईवेंट हैंडलर में, जो क्रॉस थ्रेडिंग अपवाद फेंकता है। मुझे एहसास है कि जब भी मैं किसी संपत्ति तक पहुंचता हूं, तो मैं InvokeRequired की जांच करके इससे बच सकता हूं, लेकिन मुझे इसके बारे में चिंता करने की ज़रूरत नहीं है कि उपयोगकर्ता नियंत्रण के लिए कोड लिखते समय (विशेष रूप से क्योंकि अन्य लोग कोड के इन बिट्स को भी लिखते हैं जो शायद हमेशा याद नहीं है)।

तो मेरा सवाल यह है कि क्या मैं कोशिश कर रहा हूं कि कोई भी सुरक्षित तरीका है या पृष्ठभूमि में इन नियंत्रणों को लोड करने के बारे में मुझे सबसे अच्छा कैसे जाना चाहिए? या यह मूल रूप से असंभव है और क्या मुझे नियंत्रण बनाने के लिए मुख्य धागे पर चिपकना है?

मुझे उम्मीद है कि मैंने जो जानकारी प्रदान की है वह मेरी स्थिति को स्पष्ट करने के लिए पर्याप्त है; यदि नहीं, तो मुझे विस्तार और कोड नमूने प्रदान करने में खुशी होगी।

+0

"जब तक कि मैं कोई संपत्ति सेट करने का प्रयास नहीं करता" - क्या वह थ्रेड या बाद में है? –

+0

बाद में, उपयोगकर्ता नियंत्रण को मुख्य रूप में संरक्षित किया गया है (जैसा कि form.controls.add (mycontrol) में है) –

उत्तर

3

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

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

एक सामान्य करने के लिए प्रयास कर रहा है एक फिट सभी रूपरेखा है कि यूआई धागा मोड में और पृष्ठभूमि मोड में एक ही काम करता है और बस बदतर प्रदर्शन में कभी कभी InvokeRequired परिणाम की जाँच करता है (के रूप में सभी धागे आह्वान में ब्लॉक किए गए हैं) या जैसे ही एप्लिकेशन एक उचित जटिलता तक पहुंचता है, यहां तक ​​कि (ज्ञात) deadlocks में भी। BeginInvoke में सभी अपडेट एसिंक भी कर रहे हैं, प्रत्येक विधि को अलग-अलग मानते हुए w/o, परिणामस्वरूप डेटा स्थिरता समस्याएं हो सकती हैं (यानी नियंत्रण वापस को थ्रेड के बीच आमंत्रण आदेश को वापस करने के कारण समय में अपडेट कर सकते हैं)।

+0

हां, मुझे यह महसूस हो रहा है कि मैं थोड़ा सा चालाक होने की कोशिश कर रहा था। मैंने अपना पहला प्रयास छोड़ दिया है और आपके दूसरे अनुच्छेद के समान लाइनों के साथ आगे बढ़ रहा हूं। बराबर युक्तियों के लिए धन्यवाद। 3; मुझे एहसास नहीं हुआ था। –

+0

व्यक्तिगत रूप से मैं धागे के बीच संवाद करने के लिए एक कतार (http://msdn.microsoft.com/en-us/library/7977ey2c.aspx) का उपयोग करना पसंद करता हूं: पृष्ठभूमि थ्रेड कतार में आइटम ('परिणाम') जोड़ता है, यूआई थ्रेड आइडल पर कतार की जांच करें और नियंत्रण अपडेट करें (यह ठेठ निर्माता/उपभोक्ता है)। लेकिन आपको सावधानी से विचार करना चाहिए कि क्या पृष्ठभूमि यूआई की क्षमता को आगे बढ़ाने के लिए नहीं जा सकती है, जो आसानी से हो सकती है, विशेष रूप से ग्रिड के साथ, जब तक आप विशेष उपाय नहीं करते हैं तब तक कतार नियंत्रण से बाहर हो जाती है। –

1

this answer में कोड नमूना इस समस्या के आसपास एक सुंदर तरीका प्रदान करता है।

कोड है कि इसका जवाब से उद्धृत:

public void UpdateTestBox(string newText) 
{ 
    BeginInvoke((MethodInvoker) delegate { 
     tb_output.Text = newText; 
    });   
} 

... हालांकि आपके मामले में आप नियंत्रण स्वयं पर BeginInvoke कॉल करना चाहते हैं:

public void UpdateTestBox(string newText) 
{ 
    tb_output.BeginInvoke((MethodInvoker) delegate { 
     tb_output.Text = newText; 
    });   
} 
+0

मुझे अभी तक बहुत कुछ नहीं दिख रहा है कि यह कैसे मदद करेगा। मेरा मतलब है, हाँ, आप सही हैं, निश्चित रूप से, Invoke/BeginInvoke का उपयोग करने में मदद मिलेगी, लेकिन यह वही है जो मैं टालने की कोशिश कर रहा हूं। या शायद मैं समझ में नहीं आया कि आप क्या प्राप्त कर रहे हैं। –

+1

यदि आप UI थ्रेड की तुलना में किसी भिन्न थ्रेड पर नियंत्रण बनाते हैं तो मैं नहीं देख सकता कि आप Invoke/BeginInvoke से कैसे दूर हो जाएंगे। हालांकि, सुझाया गया कोड अगर (ctl.InvokeRequired) [...] संस्करण से बहुत आसान है। बहुप्रचारित जाने की तत्काल सजा यह है कि आपको अपना सिंक्रनाइज़ेशन करने की आवश्यकता है;) –

1

InvokeRequired तंत्र का ब्यौरा जानने नहीं , मैं थोड़ा और अफ़ाइक प्रयोग कर रहा हूं, जब तक आप माता-पिता नहीं हैं (यानी कुछ नियंत्रण में शामिल हैं। नियंत्रण संपत्ति)।

तो आप अपने नियंत्रण तैयार करने, उन्हें एक सूची में स्टोर करने और उन्हें शामिल किए गए विधि में मुख्य UI से संलग्न करने में सक्षम होना चाहिए।


संपादित करें: मुझे नहीं लगता कि यह थ्रेड ने एक नियंत्रण बनाया है। तो सामान्य नियम लागू होना चाहिए, यानी आप केवल मुख्य विंडोज थ्रेड के नियंत्रण के साथ काम कर सकते हैं। और मुझे लगता है कि मानदंड माता-पिता के बजाय हैंडलक्रेटेड है। जब तक ऐसा नहीं हुआ है तब तक आपको थोड़ा राहत मिलती है।

+0

हां, ऐसा लगता है कि parenting मुझे मार रहा है। आपका विचार बहुत बुरा नहीं है, लेकिन यहां सहायता नहीं करेगा, क्योंकि जिन गुणों को मैं सेट कर रहा हूं, वे सभी उपयोगकर्ता इंटरैक्शन के जवाब में हैं, दूसरे शब्दों में * नियंत्रण के बाद मुख्य रूप से नियंत्रण किया गया है और प्रदर्शित किया गया है। यह मेरे प्रश्न से काफी स्पष्ट नहीं हो सकता है। –

+0

यह स्पष्ट था लेकिन मैं उन समस्याओं को कर रहा हूं। –

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