2009-09-04 11 views
5

संभव डुप्लिकेट:
Getting Cross-thread operation not valid
Cross-thread operation not validपार धागा आपरेशन मान्य नहीं है, जबकि एक COM पोर्ट को सुन

मैं इतना है कि मैं नए हैंडलर बनाने COM पोर्ट को सुनने के लिए कोशिश कर रहा हूँ SerialPort.DataReceived घटना के लिए। तर्क सरल है - मैं टेक्स्टबॉक्स 1 पर कुछ लिखता हूं, बटन 1 दबाता हूं और मेरा टेक्स्ट इसे लेबल 1 में स्वयं दिखाना चाहिए। लेकिन मेरा आवेदन नहीं चलना चाहता, क्योंकि यह 'क्रॉस थ्रेड ऑपरेशन मान्य नहीं है' त्रुटि फेंकता है। मैंने कुछ खोज और पाया वस्तु को आमंत्रित किया - मैं अपने उदाहरण में इसका उपयोग कैसे कर सकता हूं? मुझे आमंत्रण तर्क शामिल करने की आवश्यकता क्यों है?

namespace WindowsApplication1 
{ 
public partial class Form1 : Form 
{ 
    SerialPort sp = new SerialPort(); 

    public Form1() 
    { 
     InitializeComponent(); 
     sp.DataReceived += MyDataReceivedHandler; 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

    } 

    private void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
    { 
     try 
     { 
      //sp.PortName = "COM3"; 
      //sp.Open(); 
      Label1.Text = sp.ReadLine(); 
     } 
     catch (Exception exception) 
     { 
      RichTextBox1.Text = exception.Message + "\n\n" + exception.Data; 
     } 
     finally 
     { 
      sp.Close(); 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      sp.PortName = "COM3"; 
      sp.Open(); 
      sp.WriteLine(TextBox1.Text); 
     } 
     catch (Exception exception) 
     { 
      RichTextBox1.Text = exception.Message + "\n\n" + exception.Data; 
     } 
     finally 
     { 
      sp.Close(); 
     } 
    } 
} 

}

+0

@ पीटर: यहां COM पोर्ट आरएस 232 सीरियल इंटरफ़ेस है। यूएसबी के बावजूद और अभी भी कई डिवाइस हैं (जैसे जीपीएस, मेडिकल) जो पीसी संचार के लिए सीरियल पोर्ट का उपयोग करते हैं। – Sesh

+0

@_simon_: बस उत्सुक: इस विशेष एप्लिकेशन में COM पोर्ट का उपयोग क्या किया जाता है? –

+0

@_simon_: मैंने अपना उत्तर –

उत्तर

17

मेरा अनुमान है कि MyDataReceivedHandler जीयूआई तुलना में एक अलग धागा पर चल रहा है है। इसे ठीक करने के लिए, आपको सही धागे पर Text सेटर्स का आह्वान करने की आवश्यकता है। यह ऐसा करने का एक नमूना है:

public void SetControlText(Control control, string text) 
{ 
    if (this.InvokeRequired) 
    { 
     this.Invoke(new Action<Control,string>(SetControlText), new object[] { control, text }); 
    } 
    else 
    { 
     control.Text = text; 
    } 
} 

private void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    try 
    { 
     //sp.PortName = "COM3"; 
     //sp.Open(); 
     SetControlText(Label1, sp.ReadLine()); 
    } 
    catch (Exception exception) 
    { 
     SetControlText(RichTextBox1, exception.Message + "\n\n" + exception.Data); 
    } 
    finally 
    { 
     sp.Close(); 
    } 
} 

आप .NET फ्रेमवर्क 2.0 का उपयोग कर रहे हैं, तो ऊपर Action<T1, T2> प्रतिनिधि उपलब्ध नहीं है, तो आप अपने खुद के एक परिभाषित करना होगा:

private delegate void SetControlTextHandler(Control control, string text); 

public void SetControlText(Control control, string text) 
{ 
    if (this.InvokeRequired) 
    { 
     this.Invoke(new SetControlTextHandler(SetControlText), new object[] { control, text }); 
    } 
    else 
    { 
     control.Text = text; 
    } 
} 

SetControlText विधि (यह 2.0 और 3.5 में काम करता है) इस तरह छोटे (और यहां तक ​​स्थिर) बनाया जा सकता है:

public static void SetControlText(Control control, string text) 
{ 
    ´control.Invoke((MethodInvoker)delegate { control.Text = text; }); 
} 

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

+0

अपडेट किया है ऐसा लगता है कि यह केवल 3.5 में काम करता है। मैं विजुअल स्टूडियो 2005 का उपयोग करता हूं, अब मैंने 3.5 एसपी 1 स्थापित किया है। जहां विजुअल स्टूडियो 2005 में मैं निर्धारित कर सकता हूं कि कौन सा .NET ढांचा मैं उपयोग कर रहा हूं? – sventevit

+0

@_simon_: मैंने 2.0 संगत संस्करणों –

+0

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

0

तुम भी कर सकते हैं निम्नलिखित जब भी भी उस पर बनाया गया था से एक अलग धागे से एक UI नियंत्रण तक पहुँचने:

(.NET 3,5)

myControl.BeginInvoke(new MethodInvoker(() => myControl.whatever = whatever;)); 

या (.NET 2.0)

myControl.BeginInvoke(new MethodInvoker(delegate { myControl.whatever = whatever;)); 

संपादित करें> कभी कभी एक लंबी चलने वाली ऑपरेशन के लिए आह्वान का उपयोग कर/अभी भी ui रखती हूँ कर सकते हैं, का उपयोग कर BeginInvoke जाहिर है कि आपरेशन अतुल्यकालिक रूप से करता है, एक डी ui लटका नहीं होगा।

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