停止 Stream.BeginRead()
我需要从虚拟 com 端口读取数据并检测消息“Dreq”。一旦我按下连接按钮,它就会连接到我的 COM8 端口并开始在新线程中读取。我还有一个断开连接按钮,我希望在其中关闭读取并断开与 COM8 端口的连接。但是,我在关闭 BeginRead 时遇到问题。
public partial class Form1 : Form
{
SerialPort sp;
Stream stream;
IAsyncResult recv_result;
private void button1_Click(object sender, EventArgs e)
{
sp = new SerialPort("COM8", 9600);
sp.Open();
sp.ReadTimeout = 50000;
sp.NewLine = "\n\r\0";
stream = sp.BaseStream;
recv_result = stream.BeginRead(new byte[1], 0, 0, new
AsyncCallback(ReadCallBack), stream);
}
private void ReadCallBack(IAsyncResult ar)
{
Stream stream = (Stream)ar.AsyncState;
string temp;
while (stream.CanRead)
{
temp = sp.ReadLine();
// ... do something with temp
}
}
private void disconnectButton_Click(object sender, EventArgs e)
{
stream.EndRead(recv_result);
sp.Close();
}
}
i need to read data from my virtual com port and detect the message "Dreq". Once i press the connect button, it connects to my COM8 port and begins reading in a new thread. I also have a disconnect button in which i wish to close the reading and disconnect from the COM8 port. However, i have problems closing the BeginRead.
public partial class Form1 : Form
{
SerialPort sp;
Stream stream;
IAsyncResult recv_result;
private void button1_Click(object sender, EventArgs e)
{
sp = new SerialPort("COM8", 9600);
sp.Open();
sp.ReadTimeout = 50000;
sp.NewLine = "\n\r\0";
stream = sp.BaseStream;
recv_result = stream.BeginRead(new byte[1], 0, 0, new
AsyncCallback(ReadCallBack), stream);
}
private void ReadCallBack(IAsyncResult ar)
{
Stream stream = (Stream)ar.AsyncState;
string temp;
while (stream.CanRead)
{
temp = sp.ReadLine();
// ... do something with temp
}
}
private void disconnectButton_Click(object sender, EventArgs e)
{
stream.EndRead(recv_result);
sp.Close();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以尝试调用
sp.DiscardOutBuffer()
。它将调用您的读取回调,然后您可以使用stream.EndRead()
。You can try calling
sp.DiscardOutBuffer()
. It will call your read callback and you can then usestream.EndRead()
.你可以试试这个程序。
You can try this program.
这是一篇旧帖子,但我认为这个解决方案可以帮助遇到同样问题的人。
我在应用程序中使用遗留代码,发现 BeginRead 和 EndRead 的问题是无法取消异步操作。因此,当您关闭端口时,对 BeginRead 的调用将永远停留在那里,直到端口中收到另一个字节,然后对 EndRead 的调用将释放端口。如果不是这样发生,那么您的应用程序可能会挂起,甚至任务管理器也无法关闭它,直到您拔下串行端口电缆!
幸运的是,TPL 库可以通过一种非常简单而优雅的方式解决这个问题。 CancelToken 是您所需要的:
在端口打开时:
在端口关闭时:
请注意 while 循环比递归调用更好,因为当端口广播大量信息时,15 分钟后会引发堆栈溢出异常。
这是一个非常简单的实现。我希望它有帮助
It's an old post, but I think this solution can help people with the same problem.
I was using legacy code for an application and I found that the problem with BeginRead and EndRead is that there is no way to cancel the asynchronous operation. Therefore, when you close the port, your call to BeginRead stays there forever until another byte is received in the port, then your call to EndRead will free up the port. If it does not happen this way, then your application may hang and not even task manager can close it until you unplug the serial port cable!
Fortunately the TPL library can fix this problem in a very simple and elegant way. The CancelToken is what you need:
On port open:
On port close:
Please note a while loop is better than recursive call because when port is broadcasting lots of information, a stack overflow exception is thrown after 15 minutes.
It's a very simple implementation. I hope it helps