2011-05-03 22 views
8

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

"Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on."

की तरह एक अपवाद दिखा रहा है चलाने के मैं कैसे इस त्रुटि को हल कर सकते हैं?

+0

की [मुझे उस CrossThread साथ मदद?] संभव डुप्लिकेट (http://stackoverflow.com/questions/337165/help-me-with-that-crossthread) [इस मैं क्यों मिल रही है की – jgauffin

+0

संभव डुप्लिकेट त्रुटि: "क्रॉस-थ्रेड ऑपरेशन मान्य नहीं है: इसे बनाए गए धागे के अलावा किसी अन्य थ्रेड से नियंत्रित lbFolders को नियंत्रित करें।"?] (http://stackoverflow.com/questions/244591/why-am-i-getting- यह -errorcross-thread-operation-not-valid-control-lbfolders) –

उत्तर

9

जब विधि को नियंत्रण में कॉल किया जाता है, तो कॉलर एक अलग थ्रेड पर होता है जिस पर नियंत्रण बनाया गया था, तो आपको Control.Invoke का उपयोग करके कॉल करने की आवश्यकता है। यहां एक कोड नमूना है:

// you can define a delegate with the signature you want 
public delegate void UpdateControlsDelegate(); 

public void SomeMethod() 
{ 
    //this method is executed by the background worker 
    InvokeUpdateControls(); 
} 

public void InvokeUpdateControls() 
{ 
    if (this.InvokeRequired) 
    { 
     this.Invoke(new UpdateControlsDelegate(UpdateControls)); 
    } 
    else 
    { 
     UpdateControls(); 
    } 
} 

private void UpdateControls() 
{ 
    // update your controls here 
} 

उम्मीद है कि यह मदद करता है।

+0

नमस्कार देने के लिए हाय धन्यवाद, मैं कोड प्रदान करने की कोशिश कर रहा हूं, वास्तव में मैं बटन_क्लिक घटना में thred को कॉल करता हूं .. लेकिन यह सब कुछ और भाग में जाता है .. .. अगर इसमें यह दर्ज नहीं किया गया है (यह। इन्वोक्यूक्वायर) { यह। इन्वोक (नया प्रदर्शनसमूह निष्पादन (MyAction)); } – Victor

+0

@ विक्टर: इसका मतलब है कि इस बिंदु पर Invoke की आवश्यकता नहीं है। सुनिश्चित करें कि थ्रेड में निष्पादित सभी कोड आपके फॉर्म के नियंत्रण को अपडेट करने के लिए "सुरक्षा" (Invoke) कॉल करता है। –

+0

मैं डैनियल नहीं प्राप्त कर सकता हूं, मैं अपना कोड यहां पोस्ट कर सकता हूं .. – Victor

3

अक्सर, WinForms के साथ इस तरह की चीज करने का सबसे अच्छा तरीका BackgroundWorker का उपयोग करना है, जो आपके काम को पृष्ठभूमि धागे पर चलाएगा, लेकिन यूआई को स्थिति की रिपोर्ट करने के लिए आपको एक अच्छा साफ तरीका प्रदान करेगा।

रोज़ाना .NET प्रोग्रामिंग में, स्पष्ट रूप से धागे या कॉलिंग बनाते हैं .वॉव एक संकेत है कि आप ढांचे का उपयोग अपने पूर्ण लाभ के लिए नहीं कर रहे हैं (बेशक, कम स्तर के करने के कई वैध कारण हैं सामान भी, यह सिर्फ इतना है कि वे कम आम हैं कि लोग कभी-कभी महसूस करते हैं)।

+0

प्रतिक्रिया देने के लिए धन्यवाद, मैं इस एप्लिकेशन का उपयोग कर रहा हूं (ऊपर दिए गए लिंक में) मेरे आवेदन में पृष्ठभूमि कोड। लेकिन यह त्रुटि दिखा रहा है ... – Victor

+2

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

2

आपको यह जांचने की आवश्यकता है कि आप जिस नियंत्रण को अपडेट करने का प्रयास कर रहे हैं उसके लिए Invoke आवश्यक है। कुछ इस तरह:

Action<Control, string> setterCallback = (toSet, text) => toSet.Text = text; 

void SetControlText(Control toSet, string text) { 
    if (this.InvokeRequired) { 
    this.Invoke(setterCallback, toSet, text); 
    } 
    else { 
    setterCallback(toSet, text); 
    } 
} 
1

एक पैटर्न जो आपके लिए उपयोगी हो सकता है कार्यों कि जीयूआई के साथ बातचीत के शीर्ष पर एक जांच करने के लिए है कि क्या आप या नहीं सही धागे पर चल रहे हैं और समारोह में ही आह्वान है यदि आवश्यक हुआ। इस तरह:

public delegate void InvocationDelegate(); 

    public void DoGuiStuff(){ 
     if (someControl.InvokeRequired){ 
     someControl.Invoke(InvocationDelegate(DoGuiStuff)); 
     return; 
     } 

     //GUI manipulation here 
    } 

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

0

आह्वान

// you can define a delegate with the signature you want 
public delegate void UpdateControlsDelegate(); 

public void SomeMethod() 
{ 
    //this method is executed by the background worker 
    InvokeUpdateControls(); 
} 

public void InvokeUpdateControls() 
{ 
    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(new UpdateControlsDelegate(UpdateControls)); 
    } 
    else 
    { 
     UpdateControls(); 
    } 
} 

private void UpdateControls() 
{ 
    // update your controls here 
} 
+0

हाय पंकज पहले से ही मैंने इस कोड को आजमाया है, लेकिन जब यह सच है तो अनावश्यक रूप से झूठ बोलता है ... मैं अपने बटन क्लिक ईवेंट में अनावश्यक कहता हूं ..... – Victor

+0

इसे अपने बटनिड से प्रतिस्थापित करें और फिर से जांचें। – Pankaj

+0

मैंने इस निजी शून्य btnsiteranks_Click_1 (ऑब्जेक्ट प्रेषक, EventArgs ई) { InvokeUpdateControls(); जैसे कोड लिखा था; } सार्वजनिक शून्य InvokeUpdateControls() { अगर (this.InvokeRequired) { this.BeginInvoke (नई PerformSomeActionDelegate (Geturls)); } अन्य { गेटूरल्स(); } } – Victor

0

शुरू करने के लिए यूआई परिवर्तन Control.Invoke साथ किया जा सकता() पद्धतियों, इस पार धागा अपवाद कोड स्निपेट नीचे का उपयोग कर हल किया जा सकता आह्वान से अपडेट किया गया।

void UpdateWorker() 
{ 
    //Here ddUser is the user control 
    //Action to be performed should be called within { } as like below code 
    if (this.ddUser.InvokeRequired) 
     ddUser.Invoke(new MethodInvoker(() => { ddUser.Size = new Size(100, 100); })); 
}