2012-03-18 6 views
5

नहीं मिलता है मैं एक BackgroundWorker का उपयोग करें और यह करते हैं:क्यों मैं "क्रॉस-धागा आपरेशन मान्य नहीं है" त्रुटि

private void loadNewAsyncToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    this.Text = "RunWorkerAsync()"; 
    backgroundWorkerLoading.RunWorkerAsync(); 
} 
private void backgroundWorkerLoading_DoWork(object sender, DoWorkEventArgs e) 
{ 
    UnsafeThreadMethod("hello"); 
    EvenUnsaferThreadMethod(); 
} 

और अब दो तरीकों।

private void UnsafeThreadMethod(string text) 
{ 
    toolStripLabelRssFeedData.Text = text; 
} 

private void EvenUnsaferThreadMethod() 
{ 
    panelLoading.Visible = true; 
} 

मुझे समझ नहीं आता क्यों UnsafeThreadMethod निम्न अपवाद फेंक नहीं है लेकिन EvenUnsaferThreadMethod करता है।

क्रॉस-थ्रेड ऑपरेशन मान्य नहीं है: नियंत्रण 'पैनल लोडिंग' को उस धागे के अलावा किसी अन्य धागे से एक्सेस किया गया था जिसे नियंत्रित किया गया था।

संदेश के मुताबिक ऐसा इसलिए है क्योंकि toolStripLabelRssFeedData उसी धागे पर बनाया गया था लेकिन यह नहीं था।

मैंने सोचा कि मैं मुख्य धागे द्वारा बनाए गए नियंत्रणों को कॉल नहीं कर सकता और ProgressChanged ईवेंट का उपयोग करना होगा। क्या चल रहा है?

और मेरे पास दूसरा प्रश्न है। जब मैं ProgressChanged का उपयोग कर सकता हूं तो ऐसा करने का क्या फायदा है? मुझे क्या करना चाहिए?

private void EvenUnsaferThreadMethod() 
{ 
    if (panelLoading.InvokeRequired) 
    { 
     panelLoading.Invoke(new MethodInvoker(() => { EvenUnsaferThreadMethod(); })); 
    } 
    else 
    { 
     panelLoading.Visible = true; 
    } 
} 

उत्तर

5
पहला सवाल करने के लिए

:

  • पार धागा अपवाद नहीं है जानबूझकर डीबग मोड में फेंक दिया। इसका मतलब है कि अधिकांश जीयूआई नियंत्रणों में निर्मित InvokeRequired पर (सशर्त) कोड जांच है। पैनल की तरह।

  • जाहिर है टूलस्ट्रिप लेबल इस चेक को नहीं बनाता है। चूंकि यह नियंत्रण से प्राप्त नहीं होता है क्योंकि यह हो सकता है क्योंकि यह इस सुरक्षा नेट के दायरे से बाहर है।

के बाद से मानक अस्वीकरण "कोई भी उदाहरण सदस्यों सुरक्षित थ्रेड होने की गारंटी नहीं कर रहे हैं" ToolstripLabel मैं बस जब पाठ की स्थापना सामान्य InvokeRequired तर्क के साथ जाना होगा पर लागू होता है।

+1

के बाद लेबल पर अपनी राय देने के लिए अपना जवाब अपडेट किया। मुझे लगता है कि यह उत्तर बताता है कि ओपी क्या पूछ रहा था, यही कारण है कि स्पष्ट रूप से असुरक्षित कॉल अपवाद नहीं फेंक रहा था। यह सब इस तथ्य के चारों ओर घूमता है कि ToolStripLabel नियंत्रण से प्राप्त नहीं होता है और थ्रेड सुरक्षा की जांच नहीं कर रहा है। यह सिर्फ काम करने के लिए होता है, लेकिन जैसा कि दूसरे ने इंगित किया है, आप उस पर भरोसा नहीं कर सकते कि हमेशा के लिए सच्चे रहें। –

0

अपने दूसरा पसंद का लाभ यह है कि :)

सभी UI तत्व मुख्य यूआई धागे पर बनाई गई हैं काम करता है और क्या इस सवाल के नजरिए से ज्यादा महत्वपूर्ण है, कि कर सकता है केवल उस धागे के भीतर के भीतर मूल्यांकन किया गया हो।

यही वजह है कि अपने पहले मामले में विफल रहता है और यही कारण है अपने दूसरा मामले काम करेंगे है। Invoke()... मुख्य यूआई थ्रेड पर आवश्यक मेरहोड कॉल को पुनर्निर्देशित करेगा।

उम्मीद है कि इससे मदद मिलती है।

+0

आपके उत्तर के लिए धन्यवाद। आपने कहा कि 'UnsafeTreadMethod' काम नहीं करना चाहिए क्योंकि UI सामान एक अलग थ्रेड पर है लेकिन किसी भी तरह से यह करता है और यही वह नहीं है जिसे मैं समझ नहीं पा रहा हूं। साथ ही, आखिरी सवाल यह था कि अगर इनवोक सामग्री या 'प्रोग्रेस चेंज' और 'रनवॉर्कर कॉम्प्लेटेड' का उपयोग करना बेहतर होता है (जो काम करेगा क्योंकि वे सही धागे पर वापस आते हैं)। – pelz

+0

कि पहला मामला * कभी-कभी * काम करता है मेरे लिए अजीब लगता है। दूसरे मामले के बारे में: इस बात पर विचार करते हुए कि आप यूआई तत्व तक पहुंचते हैं, आपको * यूआई थ्रेड पर कॉल को रीडायरेक्ट करने के लिए * 'Invoke' का उपयोग करना होगा। यह अन्य तरीकों से काम नहीं कर सकता है। – Tigran

+0

किसी भी तरह यह व्यवहार करता है क्योंकि व्यवहार निर्धारित नहीं होता है। यह हॉटफिक्स पर सर्विस पैक पर इच्छानुसार तोड़ सकता है। – TomTom

3

आपके पहले प्रश्न के लिए, मुझे पूरी तरह से यकीन नहीं है, लेकिन ऑनलाइन से एक समीक्षा यह दिखाने के लिए प्रतीत होती है कि कभी-कभी यह अपवाद नहीं फेंकता है, लेकिन यह लेबल को अपडेट नहीं करेगा। क्या यह मामला यहाँ है? क्या आपका लेबल अपडेट नहीं किया जा रहा है?

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

अब, यदि यह एक अपडेट नहीं है जिसे आप कॉलिंग विधि को पारित करने का प्रयास कर रहे हैं, तो मैं सुझाव देता हूं कि RunWorkerCompleted ईवेंट के माध्यम से बस अपना रिटर्न डेटा वापस कर दें। यह आपके सभी अंतिम डेटा को मूल (UI) थ्रेड तक वापस भेजता है, ताकि यह Invoke की आवश्यकता के बिना UI को अपडेट कर सके।

तो, हाँ, Invoke पर आपका कॉल काम करेगा, हालांकि। हालांकि, समझें कि प्रत्येक अन्य घटनाओं के लिए क्या है, यह समझने में आपकी सहायता कर सकता है कि दूसरे तरीके से एक तरीके का उपयोग क्यों किया जाए।शायद ProgressChanged घटना बेहतर फिट बैठती है? यह आपके कोड को अनावश्यक चालान होने से भी अस्वीकार कर सकता है।

पहले क्ष

को अद्यतन मैं अभी भी toolstrip आह्वान की जरूरत नहीं के बारे में कुछ भी नहीं मिल सकता है। असल में मुझे Google टूल जैसे "टूलस्ट्रिपेलबेल नो क्रॉस थ्रेड अपवाद" या "टूलस्ट्रिपेलबेल इनवोक" इत्यादि का उपयोग करके विपरीत मिल रहा है। हालांकि, जैसा कि हेनक ने उल्लेख किया है, टूलस्ट्रिपेलबेल नियंत्रण से प्राप्त नहीं होता है, जिससे यह समझाया जा सकता है कि क्यों कोई चालान की आवश्यकता नहीं है। हालांकि, मेरा सुझाव यह मानना ​​है कि यह किसी भी अन्य यूआई नियंत्रण की तरह कार्य करेगा और सुनिश्चित करेगा कि यह सुरक्षित होने के लिए यूआई थ्रेड पर अपडेट किया गया है। quirks पर भरोसा न करें। बेहतर खेद से सुरक्षित है, तो आप कभी पता नहीं है, तो इस तरह बातें बदल सकता है, खासकर जब से यह तार्किक सबसे करने के लिए एक यूआई आइटम है ..,

+0

आपके उत्तर के लिए धन्यवाद। पहले प्रश्न के बारे में: हाँ, यह लेबल को ठीक से अपडेट करेगा। मेरे दूसरे प्रश्न के आपके उत्तर ने चीजों को मंजूरी दे दी। मुझे लगता है कि मेरे मामले में 'RunWorkerCompleted' जाने का तरीका है। – pelz

+0

मदद करने के लिए खुशी हुई। मैंने आगे के शोध –