我正在开发一个Windows表单应用程序,我通过按钮发送数据,并不断接收数据以更新某些仪表值。
我遇到的问题是,当读取串口时,如果数据过快,我的应用程序响应速度非常慢,例如读取时数据速率为1000Hz。
我附上了我的代码的简化版本。
什么可能导致此应用程序挂起?我读到我需要一些单独的线程?但是如何实现这个目标呢?
namespace Motor
{
public partial class Form1 : Form
{
SerialPort ComPort = new SerialPort();
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
ComPort.DataReceived +=
new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
}
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
InputData = ComPort.ReadExisting();
if (InputData != String.Empty)
{
this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
}
}
private void SetText(string text)
{
if (text.Contains("CM"))
{
// process the text content here
}
}
}
}
答案 0 :(得分:2)
这很可能是你的问题
this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
如果您的串口正在颠簸,它会一直尝试编组回UI线程。你真的需要这么快更新主UI线程吗?你不能每一秒或定期做这件事
关于声明
什么可能导致此应用程序挂起?我读到我需要一些 单独的线程?但是如何实现这个目标呢?
当数据出现时,在辅助线程上引发DataReceived事件 从SerialPort对象
收到
即它已经在辅助线程上运行,因此启动另一个线程无法帮助您
<强>更新强>
参考您的评论
1000hz是来自硬件的数据速率,它不需要 GUI要那么快,但我希望仪表能够顺利移动。
你仍然可以使它们流畅,至少仍然阻止UI限制将是你的关键,尝试缓冲200-300毫秒左右。我只是玩弄它
答案 1 :(得分:0)
使用function deleteObj(x){
var params = {Bucket: bucketName, Key: x.fileName};
bucket.deleteObject(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
});
}
来避免分块ReadLine
。
Data Recieved
本部分namespace Motor
{
delegate void SetTextCallback(string text);
public partial class Form1 : Form
{
SerialPort ComPort = new SerialPort();
string InputData = String.Empty;
SetTextCallback st;
public Form1()
{
InitializeComponent();
st = new SetTextCallback(SetText);
}
private void Form1_Load(object sender, EventArgs e)
{
OpenPort();
}
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
InputData = ComPort.ReadLine();
if (InputData != String.Empty)
{
this.Invoke(st,new object[] { InputData});
}
}
private void SetText(string text)
{
Console.WriteLine(text);//To check the return value
if (text.Contains("CM"))
{
// process the text content here
}
}
}
}
;
返回值列表(小心检查此值)
InputData
还有其他人......
现在,当你想要放弃或继续使用该值返回的代码时,它取决于你的代码。
在此代码之前,您已打开1. OK
2. >
3. + CMGS: ID_NUMBER_HERE
4. ERROR ERROR_NUMBER_HERE
。如果PORT
已关闭,则此代码不再有效。
打开港口指南
PORT
希望它有所帮助。
答案 2 :(得分:-1)
我没有编写任何示例代码,但我可以建议您使用线程或后台工作者来读取数据,这很容易理解背景工人或线程。你可以看简短的教程。尝试创建一个启动后台工作人员的按钮,然后使用该后台工作人员,您可以读取数据而不冻结。抱歉,我没有时间写例子,但在我看来,这些是主题你应该专注 (Bakcground worker or Threads) < / p>
我希望这会有所帮助。
答案 3 :(得分:-2)
尝试实现async await
更多信息: https://docs.microsoft.com/en-us/dotnet/csharp/async
https://msdn.microsoft.com/en-us/library/hh156513(v=vs.120).aspx
这是一个简单的例子(虽然我无法验证它,因为我没有运行代码的必要条件,但应该提出一个想法):
namespace Motor
{
public partial class Form1 : Form
{
SerialPort ComPort = new SerialPort();
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
ComPort.DataReceived +=
new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
}
private async void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
var size = ComPort.ReadBufferSize;
var data = new byte[size];
await ComPort.BaseStream.ReadAsync(data,0,size);
InputData += ComPort.Encoding.GetString(data);
SetText(InputData);
}
private void SetText(string text)
{
if (text.Contains("CM"))
{
// process the text content here
}
}
}
}