我是C#的新手,正在寻找有关我一直试图在Windows Form应用程序中解决的问题的一些建议。
我有一个需要通过连接的串行端口连续读取返回到程序的数据的应用程序。我有一些通过用户打开和关闭端口的按钮。我在配置“ DataReceived”事件处理程序以读取传入数据并将其显示在应用程序的文本框中时遇到麻烦。
我一直收到此错误:“跨线程操作无效:控件'textBox4'从创建该线程的线程之外的其他线程访问。”我看到这是一个线程错误,但是我无法弄清楚我的问题。
namespace Program
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
getAvailabePorts();
}
private void getAvailabePorts()
{
String[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
}
public void button1_Click(object sender, EventArgs e)
{
try
{
if (comboBox1.Text == "" || comboBox2.Text == "")
{
textBox4.Text = "Please select port settings";
}
else
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
serialPort1.Open();
}
}
catch (UnauthorizedAccessException)
{
textBox4.Text = "Unauthorized Access";
}
public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
textBox4.Text = sp.ReadExisting() + "\n";
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.Close();
textBox4.Clear();
}
}
}
}
答案 0 :(得分:1)
首先,欢迎您。
在“大”问题(编组数据)之前,让我警告您-串行端口很棘手。例如,您对“ ReadExisting”的调用可能不会返回您期望的结果-将返回当时串行端口缓冲区 中的所有内容,但可能会返回更多内容,从而覆盖已存在的内容。您的文本框。因此,您可能想追加为您的文本框添加数据。
现在是真正的问题。如评论员所述,您不能将数据从另一个线程直接发布到UI线程。不知不觉中,串行端口创建了一个新线程来接收数据。
您可以通过如下修改接收器代码来直接处理此问题:
public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort) sender;
var dataRcvd = sp.ReadExisting();
object[] dataArray = new object[1];
dataArray[0] = dataRcvd;
BeginInvoke( new postDataDelegate( postData), dataArray );
}
private delegate void postDataDelegate( string d );
private void postData( string d)
{
textBox4.Text = d;
}
这会将数据“编组”到UI线程,以便可以使用它。有很多方法可以完成此操作(在WPF和Winforms中的完成方法之间有很多差异,因此请注意这一点)。我希望这可以说明这一点。
除此以外-无需将DataReceived方法设为公开-可以在私有环境下正常工作。