2016-12-03 20 views
-2

我會用我的電腦和一個Arduino監視串口上收到的數據。 在arduino上,素描發送的USB字符串「aabb」evry 300ms。 用我想聽的電腦,並實時打印控制字符串(Textbox)。爲此,我創建了一個新的線程,它在Loop中偵聽在串口中到達的內容,當它發生時,通過在文本框中調用字符串來寫入。如果我在表單的類中部署該過程,但如果我使用外部類,則不會。爲了更好地解釋這個問題,我粘貼類爲什麼Invoke在另一個類中不起作用

class SerialPortManager 
{ 
    public SerialPort Serial = new SerialPort(); 
    private Thread thr; 
    private string Log; 
    public TextBox textLog; 
    public string LastString; 
    public bool thrIsAlive; 
    [Browsable(false)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    [EditorBrowsable(EditorBrowsableState.Advanced)] 
    [IODescriptionAttribute("ControlInvokeRequiredDescr")] 
    public bool InvokeRequired { get; private set; } 

    //DISPOSE 
    public void Dispose() 
    { 
     this.Dispose(); 
    } 

    //SET Textobox LOG 
    public void SetLogTxtB (TextBox txt) 
    { 
     textLog = txt; 
    } 

    //PORTE DISPONIBILI 
    public string[] Available_Ports() 
    { 
     return SerialPort.GetPortNames(); 
    } 

    //COSTRUTTORI 
    public SerialPortManager(string portname, int baudrate,bool InitializeConn) 
    { 
     Serial.BaudRate = baudrate; 
     Serial.PortName = portname; 
     if (InitializeConn == true) Serial.Open(); 
    } 
    public SerialPortManager() 
    { 

    } 

    //SETTA I PARAMETRI E INIZIALIZZA LA CONNESSIONE 
    public void SetConnectionParam(string portname, int baudrate, bool initializeConn) 
    { 
     Serial.Close(); 
     Serial.Dispose(); 
     Serial = new SerialPort(); 
     Serial.BaudRate = baudrate; 
     Serial.PortName = portname; 
     if (initializeConn == true) Serial.Open(); 
    } 

    //ASYNC LISTENER 
    public void AsyncListener() 
    { 
     thrIsAlive = true; 
     thr = new Thread(ThreadReader); 
     thr.Start(); 
    } 
    //PROCEDURA PER APPEND 
    public void AppendTextBox(string value) 
    { 
     if (InvokeRequired) 
     { 
      this.Invoke(new Action<string>(AppendTextBox), new object[] { value }); 
      return; 

     } 
     textLog.Text += value; 
    } 

    private void Invoke(Action<string> action, params object[] v) 
    { 
     throw new NotImplementedException(); 
    } 

    void ThreadReader() 
    { 
     while (thrIsAlive) 
     { 
      string temp = Serial.ReadLine(); 
      LastString = temp; 
      Log += LastString + "\n"; 
      AppendTextBox(LastString + "\n"); 
     } 

    } 
} 

的代碼在窗體中我寫三行

SerialPortManager PortMan = new Driver_Arduin.SerialPortManager("COM3", 9600,true); 
     PortMan.SetLogTxtB(textBox1); 
     PortMan.AsyncListener(); 

如果我嘗試運行程序返回錯誤「跨線程操作允許」。現在,當我發佈這個要求,我決定做最後的嘗試和改變方法AppendTextBox到:

public void AppendTextBox(string value) 
    { 
     if (textLog.InvokeRequired) 
     { 
      try 
      { 
       textLog.Invoke(new Action<string>(AppendTextBox), new object[] { value }); 
       return; 
      } 
      catch (ObjectDisposedException) 
      { 
       thrIsAlive = false; 
      } 
     } 
     textLog.Text += value; 
    } 

最後和它的工作原理。現在確定在發佈之前解決了問題的Stackoverflow的力量,我會知道我的代碼爲什麼工作。謝謝

回答

0

在SerialPortManager中,您必須使用委託來代替windows控件。

class SerialPortManager 
    { 
     public SerialPort Serial = new SerialPort(); 
     private Thread thr; 
     private string Log; 
     //public TextBox textLog; 
     public Action<string> textLog; 
..... 

克里特島,你簡單地形成方法:

public void SetTextBoxText(string value) 
    { 
     if (textBox1.InvokeRequired) 
     { 
      try 
      { 
       textBox1.Invoke(new Action<string>(AppendTextBox), new object[] { value }); 
       return; 
      } 
      catch (ObjectDisposedException) 
      { 
       thrIsAlive = false; 
      } 
     } 
     textBox1.Text += value; 
    } 

集代表波特曼:

SerialPortManager PortMan = new Driver_Arduin.SerialPortManager("COM3", 9600,true); 
     PortMan.SetLogTxtB=new Action<string>(SetTextBoxText); 
     PortMan.AsyncListener(); 

如果需要輸出日誌波特曼的文本框叫textLog委託。

void ThreadReader() 
    { 
     while (thrIsAlive) 
     { 
      string temp = Serial.ReadLine(); 
      LastString = temp; 
      Log += LastString + "\n"; 
      //AppendTextBox(LastString + "\n"); 
      textLog(LastString + "\n"); 
     } 

    } 
0

除此之外,您在SerialPortManagerInvoke方法應該拋出NotImplementedException的問題是,你定義自己的InvokeRequired/Invoke

您需要使用WinForms控件提供的這些方法,以便它知道您的代碼是否在創建控件的線程(UI線程)內運行,以及它如何將上下文更改爲該線程。

其實它似乎你可以使用你的SerialPortManager但使用的textLogInvokeRequired/Invoke就像你已經在做AppendTextBox

順便說一下,if (initializeConn == true)是無用的 - if (initializeConn)就足夠了。

相關問題