C# 从SerialDataReceivedEventHandler写入文本框控件
我敢肯定,只有我做得不对 我有一个C# 从SerialDataReceivedEventHandler写入文本框控件,c#,winforms,static,controller,C#,Winforms,Static,Controller,我敢肯定,只有我做得不对 我有一个Form1,它有一个按钮,onclick可以调用serialConn.cs中名为connect()的方法 这很好,但是当收到数据时,我希望它打印在我的表单1的文本框中。。 但是,由于我的DataReceivedEvent()是一个静态的(我想我必须是吗?),我不能访问任何东西? 那么最好的方法是什么呢?您需要将表单实例传递给这个connect方法(从按钮的事件处理程序): 在串行连接中: public static bool connect(string com
Form1
,它有一个按钮,onclick可以调用serialConn.cs中名为connect()
的方法
这很好,但是当收到数据时,我希望它打印在我的表单1的文本框中。。
但是,由于我的DataReceivedEvent()
是一个静态的
(我想我必须是吗?),我不能访问任何东西?
那么最好的方法是什么呢?您需要将表单实例传递给这个connect方法(从按钮的事件处理程序):
在串行连接中:
public static bool connect(string comPort, Form1 whichForm) {
然后可以使用lambda函数并关闭其中的“whichForm”引用,如下所示:
但是,此外,您应该确保不从主线程以外的其他线程实际修改GUI——这是非常可能的,因为SerialPort类的性质很可能从另一个后台线程引发事件——因此this.Invoke(其他一些lambda)它封送在主线程上执行的特定操作
MSDN明确指出:
当从SerialPort对象接收数据时,在辅助线程上引发DataReceived事件。由于此事件是在次线程而不是主线程上引发的,因此尝试修改主线程中的某些元素(如UI元素)可能引发线程异常。如果需要修改主窗体或控件中的元素,请使用Invoke将更改请求发回,这将在适当的线程上完成工作
public static bool connect(string comPort, Form1 whichForm) {
BTserial = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
BTserial.Open();
if (BTserial.IsOpen) {
BTserial.DataReceived += (sender, e) => {
Debug.WriteLine("Data Incomming!");
// Check if Chars are received
if (e.EventType == SerialData.Chars) {
Debug.WriteLine("Chars!");
// Create new buffer
byte[] ReadBuffer = new byte[BTserial.BytesToRead];
// Read bytes from buffer
BTserial.Read(ReadBuffer, 0, ReadBuffer.Length);
BTserial.DiscardInBuffer();
// Encode to string
string data = bytesToString(ReadBuffer);
Action toBeRunOnGuiThread = () => whichForm.theTextBox.Text = data;
// to guard yourself from all evil
// you could check to see if it is needed to
if (whichForm.InvokeRequired)
// marshal the call to the action all the way to the GUI thread
whichForm.Invoke(toBeRunOnGuiThread);
else
// or, if we ARE on the GUI thread already, just call it from this thread
toBeRunOnGuiThread();
ReadBuffer = null;
data = null;
}
};
return true;
} else {
return false;
}
}
您需要将表单实例传递到此连接方法(从按钮的事件处理程序):
在串行连接中:
public static bool connect(string comPort, Form1 whichForm) {
然后可以使用lambda函数并关闭其中的“whichForm”引用,如下所示:
但是,此外,您应该确保不从主线程以外的其他线程实际修改GUI——这是非常可能的,因为SerialPort类的性质很可能从另一个后台线程引发事件——因此this.Invoke(其他一些lambda)它封送在主线程上执行的特定操作
MSDN明确指出:
当从SerialPort对象接收数据时,在辅助线程上引发DataReceived事件。由于此事件是在次线程而不是主线程上引发的,因此尝试修改主线程中的某些元素(如UI元素)可能引发线程异常。如果需要修改主窗体或控件中的元素,请使用Invoke将更改请求发回,这将在适当的线程上完成工作
public static bool connect(string comPort, Form1 whichForm) {
BTserial = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
BTserial.Open();
if (BTserial.IsOpen) {
BTserial.DataReceived += (sender, e) => {
Debug.WriteLine("Data Incomming!");
// Check if Chars are received
if (e.EventType == SerialData.Chars) {
Debug.WriteLine("Chars!");
// Create new buffer
byte[] ReadBuffer = new byte[BTserial.BytesToRead];
// Read bytes from buffer
BTserial.Read(ReadBuffer, 0, ReadBuffer.Length);
BTserial.DiscardInBuffer();
// Encode to string
string data = bytesToString(ReadBuffer);
Action toBeRunOnGuiThread = () => whichForm.theTextBox.Text = data;
// to guard yourself from all evil
// you could check to see if it is needed to
if (whichForm.InvokeRequired)
// marshal the call to the action all the way to the GUI thread
whichForm.Invoke(toBeRunOnGuiThread);
else
// or, if we ARE on the GUI thread already, just call it from this thread
toBeRunOnGuiThread();
ReadBuffer = null;
data = null;
}
};
return true;
} else {
return false;
}
}
不知道你的意思。我看到了在connect()方法中运行它的想法。但是不明白:Action to berunguithread=()=>this.theTextBox.Text=data;调用(toberunguithread)代码>。。。我在(sender,e){
('=>'预期)的{
上得到syntaxt错误我为我之前犯的错误感到抱歉..再看一看代码..我错误地认为connect方法是Form1类的一部分,它是一个实例方法。然后我意识到它不是该类的一部分,它属于serialConn,并且是静态的。尝试发送表单实例(此)从按钮的click事件处理程序到您的connect方法。我重新编辑了整个帖子。通过ToBerunguithread操作,我的意思是,实际触摸表单和文本框并不是问题的结束。您还需要以非常安全的方式更改Text属性。SerialPort类在b上运行命令后台线程。这样,用户界面将永远不会冻结。用户界面线程需要不受长作业的影响,才能处理鼠标单击之类的操作。但所有这些都是有代价的。你不能从后台线程修改用户界面对象。你需要发一条消息,忘记提及这一点。因此,它是有代价的实际上是这样的:BTserial.DataReceived+=(sender,e)=>{Debug.WriteLine(“数据输入!”);//如果(e.EventType==SerialData.Chars){Debug.WriteLine(“Chars!”);检查是否收到了字符;//创建新缓冲区(不知道我是如何使用它们的:))啊,我明白了!它就像一个符咒……只是为了澄清一些事情。Lambda
意味着你采用了我的datareceived方法并将其放入我的connect中,对吗?不确定你的意思。我明白在connect()方法中运行它的想法。但不明白:Action Toberunguithread=()=>this.theTextBox.Text=data;this.Invoke(toberunguithread);
…我在(发送方,e){
(预期为“=>”的{
上得到语法错误我为我之前犯的错误感到抱歉..再看一看代码..我错误地认为connect方法是Form1类的一部分,它是一个实例方法。然后我意识到它不是该类的一部分,它属于serialConn,并且是静态的。尝试发送表单实例(此)从按钮的click事件处理程序到您的connect方法。我重新编辑了整个帖子。通过ToBerunguithread操作,我的意思是,实际触摸表单和文本框并不是问题的结束。您还需要以非常安全的方式更改Text属性。SerialPort类在b上运行命令后台线程。这样,用户界面将永远不会冻结。用户界面线程需要不受长作业的影响,才能处理鼠标单击之类的操作。但所有这些都是有代价的。你不能从后台线程修改用户界面对象。你需要发一条消息,忘记提及这一点。因此,它是有代价的实际上是:BTserial.DataReceived+=(sender,e)=>{Debug.WriteLine(“数据输入”)