如果我尝试在主WindowsForm中执行此代码,则会出现以下异常:
System.Windows.Forms.dll中发生未处理的“System.InvalidOperationException”类型异常 附加信息:跨线程操作无效:控制'richTextBox1'从其创建的线程以外的线程访问。
我发现了很多关于事件,事件处理程序和线程的信息。但是,我从未真正深入研究过事件以及如何手动创建它们或多线程。 我在MSDN上找到了这篇文章
--> Link <-- 但我真的不明白。如果尝试将输出写入richtextbox1,则会出现错误。
SerialPort Arduino = new SerialPort();
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
void Form1_Load(object sender, EventArgs e)
{
string[] k = SerialPort.GetPortNames();
cBPortWaehlen.DataSource = k;
}
private void btnOpenPort_Click(object sender, EventArgs e)
{
if (!Arduino.IsOpen)
{
Arduino.DataReceived += Arduino_DataReceived;
Arduino.BaudRate = 115200;
Arduino.PortName = cBPortWaehlen.SelectedItem.ToString();
Arduino.Open();
}
else
{
MessageBox.Show("Port schon offen");
}
}
private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.richTextBox1.AppendText(Arduino.ReadExisting());
}
private void btnClosePort_Click(object sender, EventArgs e)
{
Arduino.Close();
}
答案 0 :(得分:3)
在
中收到数据时private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.richTextBox1.AppendText(Arduino.ReadExisting());
}
该事件源自另一个线程,它监视您的Arduino。
默认情况下,winforms应用程序至少有一个线程(UI线程)。 如果您在该线程上执行代码,它将暂停UI,使其无响应。
因此,如果您希望在UI保持响应的同时在后台执行操作,则必须在单独的线程中完成此操作。
不幸的是(但由于实际原因),线程不能使用彼此的引用。
然而,他们可以互相发送消息。其中一个是调用特定操作的请求。 Windows Forms内置了一些方便的方法,以便利用它:
private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if(richTextBox1.InvokeRequired)
{
richTextBox1.Invoke(
(Action)delegate
{
richTextBox1.AppendText(Arduino.ReadExisting());
}
);
}
}
答案 1 :(得分:1)
确保您仅使用UI线程更新表单。每次当您设置访问UI组件的属性(例如this.richTextBox1.AppendText)时,请注意您将其委托给UI线程以避免跨线程异常。
你可以做点什么:delegate void UpdateDelegate(string text);
private void UpdateInformation(string text)
{
if(this.InvokeRequired)
{
UpdateDelegate ud = new UpdateDelegate(UpdateInformation);
this.BeginInvoke(ud, new object[] { text } );
}
else
{
this.myTextBox.Text = text;
}
}
您也可以使用匿名委托,但上面的内容可能更容易理解。