2011-08-24 3 views
15

बना दिया गया है मैं निम्नलिखित अपवाद उत्पन्न मिलती है:Invoke या BeginInvoke नियंत्रण पर नहीं कहा जा सकता जब तक खिड़की संभाल

Invoke या BeginInvoke नियंत्रण पर नहीं कहा जा सकता जब तक खिड़की संभाल बनाया गया है।

यह मेरा कोड है:

if (InvokeRequired) 
{ 
    BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); 
} 
else 
    Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); 

मैं इस साइट पर इस विषय से संबंधित पृष्ठों पाया, लेकिन मैं नहीं जानता कि क्या गलत है।

+1

है, ' टी हो –

+1

यदि आपके पास कोई टाइमर चल रहा है (System.Timers या System.Threading), तो जांचें कि क्या वे इस कोड को ऐसे फ़ॉर्म पर चलाने के लिए कारण बना रहे हैं, जिसे पूरी तरह से निर्मित नहीं किया गया है या डिसपोज़ किया गया है। –

+0

यह कोड कहां है, कौन सी विधि या घटना हैंडलर? उत्तर के लिए – Kev

उत्तर

47

Invoke और BeginInvoke के बीच का अंतर यह है कि पूर्व सिंक्रोनस (पूरा होने की प्रतीक्षा करता है) जबकि बाद में असीमित (आग और भूलने की तरह) है। हालांकि, यूआई संदेश लूप को एक संदेश पोस्ट करके दोनों काम करते हैं जो प्रतिनिधि को उस संदेश पर पहुंचने पर निष्पादित कर देगा।

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

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

if (IsHandleCreated) 
{ 
    // Always asynchronous, even on the UI thread already. (Don't let it loop back here!) 
    BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); 
    return; // Fired-off asynchronously; let the current thread continue. 

    // WriteToForm will be called on the UI thread at some point in the near future. 
} 
else 
{ 
    // Handle the error case, or do nothing. 
} 

या हो सकता है:

if (IsHandleCreated) 
{ 
    // Always synchronous. (But you must watch out for cross-threading deadlocks!) 
    if (InvokeRequired) 
     Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); 
    else 
     WriteToForm(finished, numCount); // Call the method (or delegate) directly. 

    // Execution continues from here only once WriteToForm has completed and returned. 
} 
else 
{ 
    // Handle the error case, or do nothing. 
} 
+0

thx। – senzacionale

+0

यह एसिंक कार्यों के लिए भी आसान है जो मुख्य UI थ्रेड पर विधियों का आह्वान करते हैं, लेकिन इनवॉइस को बुलाए जाने से पहले फॉर्म का निपटारा किया जाता है। –

7

यह आम तौर पर बहुप्रचारित परिदृश्यों में होता है जहां कुछ बाहरी स्रोत (हो सकता है कि नेटवर्कस्ट्रीम) फ़ॉर्म को ठीक तरह से शुरू करने से पहले डेटा को किसी फ़ॉर्म में धक्का दे।

संदेश को डिस्पोजेक्ट के बाद भी प्रकट किया जा सकता है।

आप यह देखने के लिए IsHandleCreated देख सकते हैं कि कोई फ़ॉर्म पहले से ही बनाया गया है, लेकिन आपको Invoke कथन के रूप में उचित त्रुटि प्रबंधन में सबकुछ डालना होगा, यदि आप अपना फॉर्म बंद करते समय अपना फॉर्म अपडेट करने का प्रयास करते हैं तो अपवाद फेंक सकता है।

2

यदि आप किसी अन्य धागे से एक नियंत्रण का उपयोग करने के लिए जा रहे हैं, तो नियंत्रण दिखाने या करने से पहले

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

1

आप शायद इसे फ़ॉर्म के निर्माता में बुला रहे हैं, उस बिंदु पर अंतर्निहित सिस्टम विंडो हैंडल अभी तक मौजूद नहीं है।

5

यहाँ मेरा उत्तर

मान लें कि "नमस्ते विश्व" लिखने के लिए एक पाठ बॉक्स करना चाहते हैं है। यदि आप "Ishandlecreated" का उपयोग करते हैं तो आपके ऑपरेशन तब नहीं होंगे जब हैंडलर अभी तक नहीं बनाए गए हैं। इसलिए यदि आप अभी तक नहीं बनाए गए हैं तो आपको खुद को CreateHandlers पर मजबूर होना चाहिए।

यहाँ यह लगता है कि आप एक घटना लागू होने से पहले अपने प्रपत्र पूरी तरह से बनाया जाता है/प्रारंभ, या कुछ बिंदु पर एक और धागा पर जहां यह shouldn समस्या के बारे में अधिक जानने के बिना मेरी कोड

if (!IsHandleCreated) 
    this.CreateControl(); 

this.Invoke((MethodInvoker)delegate 
{ 
    cmbEmail.Text = null; 

}); 
संबंधित मुद्दे