2009-08-23 14 views
7

में एक थ्रेड हर किसी को शुभ दोपहर!सीरियलपोर्ट के साथ "सुरक्षित हैंडल बंद कर दिया गया है और सी #

मैंने यह SerialPort रैपर थ्रेड किया है जो सीरियल पोर्ट से एक पंक्ति में पढ़ता है। यहां मेरा धागा कोड है।

protected void ReadData() 
{ 
    SerialPort serialPort = null; 
    try 
    { 
     serialPort = SetupSerialPort(_serialPortSettings); 
     serialPort.Open(); 

     string data; 
     while (serialPort.IsOpen) 
     { 
      try 
      { 

       data = serialPort.ReadLine(); 
       if (data.Length > 0) 
        ReceivedData(serialPort, new ReceivedDataEventArgs(data)); 

      } 
      catch (TimeoutException) 
      { 
       // No action 
      } 
     } 
    } 
    catch (ThreadAbortException) 
    { 
     if (serialPort != null) 
      serialPort.Close(); 
    } 
} 

जब मैं myThread.Abort(); फोन मैं "सुरक्षित संभाल बंद कर दिया गया" (कोई रेखा या कोड के संदर्भ में) एक अपवाद मिलता है। क्या कोई यह बता सकता है कि मैं क्या गलत कर रहा हूं? धन्यवाद।

वैसे, मेरे पास Start() और Stop() है जो थ्रेड बनाता है और सम्मान को थ्रेड करता है।

+0

मैंने कुछ उदाहरण कोड जोड़ा है –

उत्तर

10

मुझे संदेह होगा कि ऐसा इसलिए है क्योंकि आप धागे को समाप्त करने के लिए थ्रेड.एबॉर्ट का उपयोग कर रहे हैं - जो आम तौर पर फेंक दिया जाता है। थ्रेड व्यवहार जब आप abortable अनुमानित नहीं है। इसकी वजह से, सीरियल पोर्ट मूल कोड पर एक रैपर है, इसलिए मूल संसाधन हैं - .NET में एक सेफहैंडल द्वारा प्रतिनिधित्व - जो अप्रत्याशित रूप से निपटाया जाता है और इसलिए आप अपवाद प्राप्त करते हैं।

आप क्या इस तरह से अपनी धागा के साथ होता है के बारे में सोच सकते हैं:

  • क्या आप सीरियल पोर्ट (जो देशी संसाधन आवंटित और उपयोग करता SafeHandle खोलने अपने धागा
  • शुरू उन लोगों के लिए पर पकड़ (रों) संसाधन)
  • आप कुछ बिंदु पर
  • तो सीरियल पोर्ट से पढ़ना शुरू (अपने धागा करने के लिए अप्रत्याशित) आप उस पर Thread.Abort फोन
  • सबसे अधिक संभावना आपके सूत्र में कोड था पर है टी बिंदु सीरियल पोर्ट (डेटा पढ़ने के लिए)
  • धागा की मौत हो जाती है और सीरियल पोर्ट संभाल परोक्ष नष्ट हो जाता है
  • आप एक अपवाद ReadLine (अंदर कोड से फेंका मिल) सीरियल पोर्ट की वजह से समारोह का उपयोग करने की कोशिश कर रहा यह हैडल अब मान्य नहीं है

आपको वास्तव में थ्रेड को रद्द करने के लिए एक अलग विधि का उपयोग करना चाहिए ताकि आपको धारावाहिक बंदरगाह को बंद करने और निपटाने का उचित मौका मिल सके।

protected ManualResetEvent threadStop = new ManualResetEvent(false); 

protected void ReadData() 
{ 
    SerialPort serialPort = null; 
    try 
    { 
     serialPort = SetupSerialPort(_serialPortSettings); 
     serialPort.Open(); 

     string data; 
     while (serialPort.IsOpen) 
     { 
      try 
      { 

       data = serialPort.ReadLine(); 
       if (data.Length > 0) 
        ReceivedData(serialPort, new ReceivedDataEventArgs(data)); 

      } 
      catch (TimeoutException) 
      { 
       // No action 
      } 

      // WaitOne(0) tests whether the event was set and returns TRUE 
      // if it was set and FALSE otherwise. 
      // The 0 tells the manual reset event to only check if it was set 
      // and return immediately, otherwise if the number is greater than 
      // 0 it will wait for that many milliseconds for the event to be set 
      // and only then return - effectively blocking your thread for that 
      // period of time 
      if (threadStop.WaitOne(0)) 
       break; 
     } 
    } 
    catch (Exception exc) 
    { 
     // you can do something here in case of an exception 
     // but a ThreadAbortedException should't be thrown any more if you 
     // stop using Thread.Abort and rely on the ManualResetEvent instead 
    } 
    finally 
    { 
     if (serialPort != null) 
      serialPort.Close(); 
    } 
} 

protected void Stop() 
{ 
    // Set the manual reset event to a "signaled" state --> will cause the 
    // WaitOne function to return TRUE 
    threadStop.Set(); 
} 
बेशक

, ईवेंट पद्धति का उपयोग करके धागा आप करने के लिए है को रोकने के लिए एक घटना में शामिल करने के लिए सावधान रहना:

एक उचित तरीका है अपने धागा बंद करने के लिए इस तरह की एक ManualResetEvent का उपयोग कर लागू किया जा सकता अपने सभी लंबे समय तक चलने वाले लूप या कार्य में राज्य की जांच करें। यदि आप नहीं चाहते हैं कि आपका धागा घटना को आपकी सेटिंग का जवाब न दे - तब तक जब तक यह लंबे समय तक चलने वाले लूप, या कार्य से बाहर न हो जाए और घटना को सेट करने के लिए "देखने" का मौका मिलता है।

+0

मेरा धागा बंद करने का सही तरीका क्या होगा। जब मैं बंदरगाह को फिर से कॉन्फ़िगर करता हूं तो 'रोकें() '/' प्रारंभ() 'का उपयोग किया जाता है। –

+0

कुछ तरीके हैं जो आप कर सकते हैं और मैंने मैनुअल रीसेट इवेंट का उपयोग करके एक उदाहरण दिया है जो एक सुंदर आम तंत्र है .. –

+0

मीठे। धन्यवाद! –

0

इसी तरह की स्थिति में भाग लें जहां मैंने एक विधि के लिए स्थानीय सीरियल पोर्ट कनेक्शन बनाने का प्रयास किया।

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

प्रत्येक बार विधि के माध्यम से मैं अपने सीरियलपोर्ट ऑब्जेक्ट्स को बना/त्याग दूंगा। उफ़। ऐसा इसलिए होता है कि यदि जीसी उस समय तक नहीं चला था जब मैंने विधि को फिर से बुलाया तो यह पहला कनेक्शन बदलने के लिए दूसरा सीरियल कनेक्शन बनाने का प्रयास करेगा और वे टकराएंगे। यह इस त्रुटि को ट्रिगर करेगा।

समाधान: कक्षा में सभी सीरियल पोर्ट कनेक्शन ऑब्जेक्ट्स को वैश्विक बनाएं। बदसूरत हैक: हाँ, लेकिन यह काम करता है

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