2010-10-24 17 views
5

मैंने हाल ही में उन वास्तव में बुरे साक्षात्कारों में से एक किया है, जहां वे आपके साथ अच्छे पुलिस/बुरे पुलिस खेलते हैं। जो भी मैंने जवाब दिया वह उनमें से एक के लिए पर्याप्त नहीं था और मेरा आत्मविश्वास मिनट से मिनट में घट रहा था। उनका अंतिम प्रश्न जो वास्तव में मुझे उलझन में था:साक्षात्कार प्रश्न: जब Control.InvokeRequired क्या आप Control.Invoke या Control.BeginInvoke का उपयोग करते हैं?

यदि किसी नियंत्रण को InvokeRequired की आवश्यकता होगी तो इसमें कोई अंतर होगा .वॉव याबिनइनवोक?

मैं आपको एक उदाहरण दिखा, मैं कैसे इसे समझने:

public delegate string WorkLongDelegate(int i); 

var del = new WorkLongDelegate(WorkLong); 
var callback = new AsyncCallback(CallBack); 
del.BeginInvoke(3000, callback, del); 

public string WorkLong(int i) 
{ 
     Thread.Sleep(i); 
     return (string.Format("Work was done within {0} seconds.", i));    
} 

private void CallBack(IAsyncResult ar) 
{ 
    var del = (WorkLongDelegate) ar.AsyncState; 
    SetText2(del.EndInvoke(ar)); 
} 

private void SetText2(string s) 
{ 
    if(InvokeRequired) 
    { 
     // What is the difference between BeginInvoke and Invoke in below? 
     BeginInvoke(new MethodInvoker(() => textBox1.Text = s)); 
    } 
    else 
    { 
     textBox1.Text = s; 
    } 
} 

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

उत्तर

15

Invokeयूआई धागा को रोकता नहीं है। यह यूआई थ्रेड पूरा होने तक थ्रेड को जारी रखने से रोकता है।

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

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

+2

इस वजह से, 'थ्रो-सुरक्षा सेटअप के आधार पर' Invoke' deadlocks के लिए कमजोर है –

0

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

आमतौर पर, यह तेजी से (पृष्ठभूमि धागे के लिए) होना चाहिए, जो मैं अनदेखा करता हूं।

5

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

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

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