2016-12-03 50 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)就足够了。