我有一个类似于“显示串行进入文本框 - 跨线程操作”的问题,但我不明白给出的答案。如何更新C#窗口与接收到的串口串口文本框?
基于我找到的教程视频示例,我创建了一个非常简单的C#表单来发送/接收串行数据。效果很好,但该示例要求您单击一个按钮来接收数据,而我现在希望通过更新“已收到”文本框自动显示接收到的数据。
Program.cs是VSE2015产生:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace spcontrol
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.cs中示出基于教程示例工作码(即, “接收” 按钮必须被点击):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace spcontrol
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
GetAvailablePorts();
//serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_OnReceiveData);
}
void GetAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
comboBox_portnames.Items.AddRange(ports);
}
private void button_openport_Click(object sender, EventArgs e)
{
try
{
if (comboBox_portnames.Text == "" || comboBox_baudrate.Text == "")
{
textBox_received.Text = "Please select port settings.";
}
else
{
textBox_received.Text = "";
serialPort1.PortName = comboBox_portnames.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox_baudrate.Text);
serialPort1.Open();
button_send.Enabled = true;
button_receive.Enabled = true;
textBox_sent.Enabled = true;
button_openport.Enabled = false;
button_closeport.Enabled = true;
comboBox_portnames.Enabled = false;
comboBox_baudrate.Enabled = false;
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
serialPort1.Handshake = Handshake.None;
label_config.Text = serialPort1.PortName + " " + serialPort1.BaudRate + " 8N1 None";
progressBar_status.Value = progressBar_status.Maximum;
}
}
catch (UnauthorizedAccessException)
{
textBox_received.Text = "Unauthorized access.";
}
}
private void button_closeport_Click(object sender, EventArgs e)
{
serialPort1.Close();
button_send.Enabled = false;
button_receive.Enabled = false;
textBox_sent.Enabled = false;
button_openport.Enabled = true;
button_closeport.Enabled = false;
comboBox_portnames.Enabled = true;
comboBox_baudrate.Enabled = true;
progressBar_status.Value = progressBar_status.Minimum;
}
private void button_send_Click(object sender, EventArgs e)
{
serialPort1.WriteLine(textBox_sent.Text);
textBox_sent.Text = "";
textBox_sent.Focus();
}
private void button_receive_Click(object sender, EventArgs e)
{
try
{
textBox_received.Text = serialPort1.ReadLine();
}
catch (TimeoutException)
{
textBox_received.Text = "Timeout exception.";
}
}
//private void port_OnReceiveData(object sender, SerialDataReceivedEventArgs e)
//{
// SerialPort sp = (SerialPort)sender;
// textBox_received.Text += sp.ReadExisting();
//}
}
}
注释掉的代码是我尝试自动处理接收到的数据文本框显示(取消注释此代码并注释掉“button_rec”中的“try”语句。eive_Click”功能)
但这样做给我的跨线程错误:
Exception thrown: 'System.InvalidOperationException' in System.Windows.Forms.dll An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll Additional information: Cross-thread operation not valid: Control 'textBox_received' accessed from a thread other than the thread it was created on.
我读过有关使用调用或BeginInvoke的东西,但从未有足够的上下文中的答案对我来说(非 - 程序员)弄清楚如何实现,再加上通常答案遍布整个地图,并且没有共识哪个是正确的/最好的。有人可以提供一个简单的解决方案,我需要添加到我的代码,使其工作? 谢谢。
ipavlu,我很欣赏这个解释。而且由lhdina分享的代码解决了我的问题。我没有在这个UI中做任何其他处理,所以我想Invoke方法对我来说已经足够了。 – jpc2112