我会使用我的电脑和Arduino监控串口上收到的数据。
在arduino上,草图向USB发送了字符串“aabb”evry 300ms。
使用pc我想听,并实时在控件(Textbox
)中打印字符串。为此,我创建了一个新的线程,它在循环中监听到达串行端口的内容,当它发生时,它通过调用文本框中的字符串来编写。如果我在表单的类中部署,但是如果我使用外部类,它不会。为了更好地解释这个问题,我粘贴了类的代码
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 :(得分:0)
除了Invoke
中的SerialPortManager
方法应该抛出NotImplementedException
之外,问题在于您定义了自己的InvokeRequired
/ Invoke
。
您需要使用WinForms控件提供的这些方法,以便它知道您的代码是否在创建控件的线程(UI线程)内运行,以及它如何将上下文更改为此线程。
实际上,您似乎可以使用SerialPortManager
但使用InvokeRequired
的{{1}} / Invoke
,就像您在textLog
中所做的一样。< / p>
BTW,AppendTextBox
相当无用 - if (initializeConn == true)
就足够了。
答案 1 :(得分:0)
在SerialPortManager中,您必须使用委托代替Windows控件。
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();
将委托设置为PortMan:
void ThreadReader()
{
while (thrIsAlive)
{
string temp = Serial.ReadLine();
LastString = temp;
Log += LastString + "\n";
//AppendTextBox(LastString + "\n");
textLog(LastString + "\n");
}
}
如果需要输出日志到PortMan的TextBox调用textLog委托。
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"LoginSuccess"] == YES)
{
//button hide
profile.hidden = NO;
}
}