【发布时间】:2017-07-24 18:47:39
【问题描述】:
我有一个类似于“在文本框中显示序列 - 跨线程操作”主题的问题,但我不明白为此给出的答案。
根据我找到的教程视频示例,我创建了一个非常简单的 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_receive_Click”函数中的“try”语句。)
但是这样做会给我带来跨线程错误:
抛出异常:“System.InvalidOperationException”在 System.Windows.Forms.dll 类型未处理的异常 'System.InvalidOperationException' 发生在 System.Windows.Forms.dll 附加信息:跨线程 操作无效:从线程访问的控件“textBox_received” 除了创建它的线程之外。
我已经阅读了有关使用 Invoke 或 BeginInvoke 的内容,但对于我(非程序员)来说,答案中没有足够的上下文来弄清楚如何实现,而且通常答案都在地图上并且没有达成共识这是正确的/最好的。有人可以为我需要添加到我的代码中以使其工作的内容提供一个简单的解决方案吗? 谢谢。
【问题讨论】:
标签: c# multithreading winforms textbox serial-port