2009-10-27 10 views
6

मेरे पास एक बड़े ऐप के साथ कुछ थ्रेडिंग समस्याएं हैं जिन पर मैं काम कर रहा हूं (क्रॉस-थ्रेड अपवाद प्राप्त कर रहा हूं)। क्या थ्रेड नाम/आईडी ढूंढने का कोई तरीका है जिस पर एक विशेष नियंत्रण बनाया गया था?क्या नियंत्रण के मालिक धागे को खोजने का कोई तरीका है?

त्रुटि तब होती है जब मैं अपने नियंत्रण के नियंत्रण संग्रह में नया नियंत्रण जोड़ने का प्रयास करता हूं। मैं वास्तव में एक छोटा, पुनरुत्पादित नमूना नहीं बना सकता, इसलिए मैं इसे जितना संभव कर सकता हूं उतना ही वर्णन करूंगा।

मेरे पास एक मुख्य नियंत्रण है जो एक फॉर्म पर बैठता है, इसे _mainControl कहते हैं। इसके निर्माता में मैं एक और नियंत्रण का एक उदाहरण का दृष्टांत, की तरह कुछ

ChildControl _childControl = new ChildControl(); 

अब _childControl मौजूद है, लेकिन मैं अभी तक _mainControls संग्रह में जोड़ना नहीं है।

आखिरकार, _mainControl को एक ईवेंट अधिसूचना प्राप्त होती है कि मुझे नियंत्रण जोड़ना चाहिए। ईवेंट हैंडलर में मैं अगर this.InvokeRequired की जाँच करें और अगर ऐसा है, मैं हैंडलर आह्वान, निम्नलिखित की तरह कुछ:

AddControlEventHander(...) 
{ 
    if(InvokeRequired) 
    { 
     BeginInvoke(new MethodInvoker(AddControlEventHander); 
     return; 
    } 
    Controls.Add(_childControl); 
} 

अपवाद हमेशा Controls.Add ("क्रॉस-धागा आपरेशन मान्य नहीं पर फेंक दिया जाता है: "_item 'को थ्रेड के अलावा किसी थ्रेड से एक्सेस किया गया था जिसे" "बनाया गया था।

अब, मुझे समझ में नहीं आता कि यह कैसे संभव है। मैंने उसी थ्रेड पर _childControl बनाया है जिस पर _mainControl बनाया गया था। जब मैं डीबगिंग कर रहा हूं, तो थ्रेड विंडो को देखते समय, जब मैं नियंत्रण कॉल करता हूं तो वर्तमान थ्रेड नाम/आईडी समान होता है। जैसा कि _childControl जोड़ा गया था। हालांकि, मुझे सबसे ज्यादा भ्रमित करने वाली चीज _mainControl से निम्नलिखित कॉल हैं:

InvokeReuqired == false; 
_childControl.InvokeRequired == false; 
_childControl._item.InvokeRequired == true; //I made _item public just to try this and it returns true! 

यह कैसे संभव है? क्या _childControl को एक थ्रेड पर बनाया जाना संभव है जबकि इसके बच्चे किसी अन्य तरीके से बनाए जाते हैं? _childControl के सभी बच्चे प्रारंभिकरण के दौरान बनाए जाते हैं, जैसा आमतौर पर किया जाता है।

यदि किसी के पास कोई सुझाव/सुझाव है कि क्या हो रहा है, तो कृपया मुझे बताएं।

धन्यवाद।

संपादित करें:

मामले में किसी को भी रुचि रखता है, मुझे पता चला क्या हो रहा था। मैं उत्सुक था कि कैसे एक धागे पर नियंत्रण बनाया जा सकता है और इसके बच्चों को एक और धागे पर बनाया गया है, भले ही InitializeComponent एक ही धागे पर किया गया हो। इसलिए, मुझे पता चला कि चार्ल्स ने नीचे सुझाए गए कोड के समान कोड का उपयोग करने के लिए कौन सा धागा बनाया था। एक बार मुझे पता था कि, मुझे कम से कम पता था कि किस धागे पर ध्यान केंद्रित करना है। तब मैंने बाल नियंत्रण के ऑनहैंडलक्रेटेड कार्यक्रम को तोड़ दिया और इस मुद्दे को पाया।

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

मदद लोगों के लिए धन्यवाद :)

+0

संकेत के लिए धन्यवाद। मैंने इसी तरह खोजा कि निर्दोष 'अगर (नियंत्रण। हैंडल! = शून्य) ... 'वास्तव में उस धागे पर नियंत्रण बनाता है! –

+0

मेरा जवाब यहां देखें http://stackoverflow.com/questions/8331144/ensuring-that-child-controls-are-created-in-main-ui-thread/17054689#17054689 –

उत्तर

3

एक नियंत्रण के लिए मालिक धागा पाने के लिए, इस प्रयास करें:

private Thread GetControlOwnerThread(Control ctrl) 
{ 
    if (ctrl.InvokeRequired) 
     ctrl.BeginInvoke(
      new Action<Control>(GetControlOwnerThread), 
      new object[] {ctrl}); 
    else 
     return System.Threading.Thread.CurrentThread; 
} 

सकते हैं बच्चे को नियंत्रण माता पिता (कंटेनर नियंत्रण) से भिन्न धागे पर हो सकता है? हां, यह सब इस बात पर निर्भर करता है कि नियंत्रण कब बनाया गया था (नया ')

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

+0

हम्म। तो जब आप यह देखने का प्रयास करते हैं कि नियंत्रण के लिए InvokeRequired की आवश्यकता है या नहीं, तो किस प्रकार की जांच की आवश्यकता है? क्या आपको हमेशा नियंत्रण और उसके सभी बच्चों पर InvokeRequired की जांच करने की आवश्यकता है? – Flack

+0

हां, आपको हमेशा InvokeRequired जांचना होगा ... क्योंकि आप कभी भी नहीं जानते कि आप जिस विधि को कोड कर रहे हैं उसमें क्या थ्रेड कॉल हो रहा है ... चाहे आपको प्रत्येक बच्चे के नियंत्रण के लिए अलग-अलग आमंत्रण की जांच करने की आवश्यकता हो, इस बात पर निर्भर करता है कि आप सभी कैसे हैं नियंत्रण एक ही थ्रेड पर बनाए गए थे या नहीं। यदि सभी नियंत्रण बनाए जाते हैं, जब फॉर्म बनाया जाता है, उसी प्रारंभिक दिनचर्या में, तो आप शायद यह मानने के लिए सुरक्षित हैं कि वे सभी एक ही थ्रेड पर बनाए गए थे। –

+0

यह मेरे लिए इतना अजीब लगता है। जो मैं बता सकता हूं, _childControl और उसके सभी बच्चे दिखते हैं कि वे एक ही थ्रेड पर बनाए गए हैं। इसके अलावा, अगर _childControls बच्चों को किसी भी तरह से किसी थ्रेड पर बनाया गया था, तो मुझे नहीं लगता कि मैं _mainControl के नियंत्रण कैसे कॉल कर सकता हूं। क्योंकि जब यह क्रॉस-थ्रेडिंग के कारण _childControl हैंडल बनाया जा रहा है, तब से यह विफल हो जाता है। या तो मैं _childControl या अपने बच्चों के कारण विफल रहता हूं। मैं नहीं देखता कि यह कैसे संभव है। मैं इसे फिर से देखूंगा और कुछ रिफैक्टरिंग करूँगा। हो सकता है कि यह अभी चलेगा :) – Flack

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