2011-07-15 151 views
1

經過大量的研究,我仍然難倒了。我有一個連續讀取數據的串口對象。我所能做的就是生成dataReceived事件,與端口通信,並將接收到的值輸出到調試窗口。所以,我很確定這一切都在身體上運作。問題是當我嘗試將串行端口輸出傳遞給我的原始線程時出現錯誤。它說我不能有線程交叉討論(或者是那種效果)。我一直在嘗試使用backgroundWorker,但我不確定這是我想要的解決方案,加上我的新手技能有點超出我的頭腦。我試圖使用調用,但該方法似乎不可用。 (我可能是從錯誤的對象調用?)無論如何部分在下面。線程之間的串口通信

namespace Photometer 
{ 
    class csRadiometerILT1700 
    { 
     //manufacturer specs for baud rate, databits, and stop bits 
     static string portName="COM1"; 
     static int baudRate = 1200; 
     static int dataBits = 8; 
     //instantialize a serial port object for the Radiometer 
     private SerialPort RadiometerSerial = new SerialPort(portName, baudRate, Parity.None, dataBits, StopBits.One); 


     //constructor 
     //public csRadiometerILT1700(Form ParentForm, Chart outputChart) 
     public csRadiometerILT1700() 
     { 


      //two handshaking properties of the ILT1700. Handshaking is enabled and 
      //http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output 
      RadiometerSerial.Handshake= Handshake.RequestToSend; 
      RadiometerSerial.DtrEnable = true; 

      RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived); 

     } 

     public void openPort() 
     { 
      if (!RadiometerSerial.IsOpen) 
      { 
       RadiometerSerial.Open(); 
      } 

     } 
     public void closePort() 
     { 
      RadiometerSerial.Close(); 
     } 

     string RadiometerVoltageReadingString; 
     int RadiometerVoltageReadingInt; 
     private void RadiometerSerial_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 
      //It's here that this.invoke()... cannot be called. 

      RadiometerVoltageReadingString= (RadiometerSerial.ReadExisting().ToString()); //y-value 
      Debug.Print(RadiometerVoltageReadingString.ToString()); 

      makeRadioReadingDouble(RadiometerVoltageReadingString); 

     } 

     private void makeRadioReadingDouble(string inputVoltageString) 
     { 

      List<double> outputVoltageDouble=new List<double>(2); 


      if (!(inputVoltageString == "\r\n" || inputVoltageString == "")) 
      { 
       string[] voltageValAndExpo = inputVoltageString.Split(new string[] { "e", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 

       for (int inCounter = 0; inCounter < voltageValAndExpo.Count(); inCounter=inCounter+2) 
       { 
        double voltageVal = Convert.ToDouble(voltageValAndExpo[inCounter]); 
        double voltageExpo = Convert.ToDouble(voltageValAndExpo[inCounter + 1]); 

        outputVoltageDouble.Add(Math.Pow(voltageVal, voltageExpo)); 
       } 
      } 
     } 

    } 
} 

這是當我形成任何有識之士的讚賞碼

  csRadiometerILT1700 Radiometer; 

      ... 

      Radiometer = new csRadiometerILT1700(); 
      Radiometer.openPort(); 

加載所有調用。

編輯: 我改變了我的csRadiometerILT1700構造函數

public csRadiometerILT1700(Form inputForm) 
    { 

     //inputForm.Invoke(
     //two handshaking properties of the ILT1700. Handshaking is enabled and 
     //http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output 
     RadiometerSerial.Handshake= Handshake.RequestToSend; 
     RadiometerSerial.DtrEnable = true; 

     RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived); 
     inputForm.Invoke(DataReceived); 
    } 

,並在csRadiometerILT1700類中聲明

public event Delegate DataReceived; 

。但是這給了我「數據接收必須是委託類型」的錯誤。我現在如何解決這個問題?我在正確的軌道上嗎?

+0

請勿從ctor中調用。以下是設置事件的鏈接:http://stackoverflow.com/questions/2448487/how-to-dispatch-events-in-c/2448530#2448530 –

+0

當收到有意義的數據時,您的課程應該提高其事件。將它打包成一個EventArgs派生類。表單訂閱(+ =)並在其處理程序中調用。 –

回答

2
  1. 您的RadiometerILT1700類需要event來報告它收到(和處理)的數據。
  2. 您的表單訂閱了該事件
  3. Forms事件處理程序使用this.Invoke()來克服跨線程問題。
+0

1.這是否會在DataReceived事件中觸發?一旦我完成處理X數量的串行數據,我會標記事件? 2.如何從通話表單訂閱? 3.這是否意味着我把「訂閱」放在Invoke()中? – Brad

+0

1)是的,2)與'+ ='一樣,與其他事件一樣,3)不,您調用表單訂閱的Form方法。到另一個或相同的方法。 –

+0

對不起,我還是輸了。我可能需要多一點手牌。你能用更多的詞來描述與2)相關的行動嗎? – Brad

0

無論何時您嘗試從其他線程發佈到主線程,您都會遇到此錯誤。您需要對要從不是主窗體線程的線程調用的控件使用委託和調用。

0

假設誤差實際上是:從比它 創建的線程以外的線程訪問

控制控制名稱。

問題是你不能從另一個線程影響你的GUI。您需要使用invoke表單或控件來傳遞控件,以便修改它。您應該能夠與大多數其他元素交互,但不能與表單交互。

0

你不應該在那裏調用this.Invoke,你這樣做的方式就像試圖將你自己的線程與你自己的線程同步到UI。你應該叫formhandle.Invoke,或窗體類寄存器內的事件,然後你可以使用this.invoke

1

Invoke是一個DelegateFormControl的方法,因爲csRadiometerILT1700是沒有這些是不是繼承了其調用實行這些類。

您將需要提出另一個事件的csRadiometerILT1700呼叫者和hadle上優桂某處(任何跨線程問題一起)。另外,你可以提供csRadiometerILT1700與委託它可以使用回調,有點像手卷事件。

一旦你的表單中有數據,你可以使用Control.InokeRequired來檢測跨線程情況,並且使用Control.Invoke來進行跨線程調用。

+0

我想我對委託語法感到困惑。呼叫形式中的哪些部分以及哪些部分在事件處理的類中進行? – Brad

+0

'delegate'是函數簽名的定義。 'Delegate'或'MultiCastDelegate'是代表'delegate'實例的類。 一個'event'是一個指定'委託'的'MulticastDelegate',帶有一個用於「引發」或「調用」調用的快捷方式。 – Jodrell

+0

'delegate'可以在任何地方聲明,'event'應該放在想要提升它的類上。匹配並用於訂閱事件「MulticastDelegate」的函數應該位於想要處理事件的類上。 – Jodrell