当前位置: 首页 > 编程语言 > C#

StopStream.BeginRead()分享

时间:2023-04-10 19:28:47 C#

StopStream.BeginRead()我需要从我的虚拟COM端口读取数据并检测消息“Dreq”。按下连接按钮后,它连接到我的COM8端口并开始读取新线程。我还有一个断开连接按钮,我想关闭读取并断开与COM8端口的连接。但是,我无法关闭BeginRead。publicpartialclassForm1:Form{SerialPortsp;流流;IAsyncResult接收结果;privatevoidbutton1_Click(objectsender,EventArgse){sp=newSerialPort("COM8",9600);sp.Open();sp.ReadTimeout=50000;sp.NewLine="nr";stream=sp.BaseStream;recv_result=stream.BeginRead(newbyte[1],0,0,newAsyncCallback(ReadCallBack),stream);}privatevoidReadCallBack(IAsyncResultar){Streamstream=(Stream)ar.AsyncState;字符串温度;while(stream.CanRead){temp=sp.ReadLine();//...用temp做点什么}}privatevoiddisconnectButton_Click(objectsender,EventArgse){stream.EndRead(recv_result);sp.Close();您可以尝试调用sp.DiscardOutBuffer()。它将调用您的读取回调,然后您可以使用stream.EndRead()。privatevoiddisconnectButton_Click(objectsender,EventArgse){sp.DiscardOutBuffer();stream.EndRead(recv_result);sp.Close();你可以试试这个程序。使用系统;使用System.Windows.Forms;使用System.IO.Ports;使用系统线程;使用System.IO;使用系统文本;公共类clsState{privateconstintBUFFER_SIZE=1024;publicbyte[]BytesBuffer=newbyte[BUFFER_SIZE];公共串行端口sp;公共流流;}publicpartialclassForm1:Form{SerialPortsp;流流;IAsyncResult接收结果;布尔结束循环=假;线程_readThread;privateManualResetEvent_readDone=newManualResetEvent(false);privatevoidbutton1_Click(objectsender,EventArgse){sp=newSerialPort("COM8",9600);sp.Open();sp.ReadTimeout=50000;sp.NewLine="nr";stream=sp.BaseStream;//将串口和流保存到状态对象clsStatestate=newclsState();状态.sp=sp;state.stream=流;//创建工作线程endLoop=false;_readThread=newThread(()=>ReadThreadProc(state))_readThread.IsBackground=true;_readThread.Start();}privatevoidReadThreadProc(clsStatestate){while(endLoop==false){//在一个线程通过后立即打开然后关闭门_readDone.Reset();//开始异步读取recv_result=state.stream.BeginRead(state.BytesBuffer,0,state.BytesBuffer.Length,newAsyncCallback(ReadCallBack),state.stream);//工作线程块在这里(等待..._readDone.Set())_readDone.WaitOne();}}privatevoidReadCallBack(IAsyncResultar){stringtemp;intbytesRead=0;//从IAsyncResult读取串口和流clsStatestate=(clsState)ar.AsyncState;//如果串行端口打开并且..if(state.sp.IsOpen){//流可以读取then..if(state.stream.CanRead){//等待异步读取完成bytesRead=state.stream.EndRead(ar);}}if(bytesRead>0){//将state.BytesBuffer中的数据从字节数组转换为字符串并保存到临时变量temp=Encoding.ASCII.GetString(state.BytesBuffer);//为下一个数据打开门_readDone.Set();}}私人的voiddisconnectButton_Click(objectsender,EventArgse){//结束循环并终止工作线程...endLoop=true;//释放开始读取_readDone.Set();if(_readThread!=null){if(_readThread.IsAlive){//如果工作线程仍然存在_readThread.Join();//在这里等待线程关闭..}}//关闭串口if(sp.IsOpen)sp.Close();//关闭流并处理它if(stream.CanRead||stream.CanWrite){stream.Close();stream.Dispose();这是一个旧帖子,但我认为这个解决方案可以帮助那些有同样问题的人我正在使用遗留代码在应用程序中,我发现BeginRead和EndRead的问题是没有办法取消异步操作.因此,当您关闭端口时,您对BeginRead的调用将永远停留在那里,直到端口接收到另一个字节,然后您对EndRead的调用会释放该端口。如果这没有发生,那么您的应用程序可能会挂起,甚至任务管理器也无法关闭它,直到您拔下串行端口电缆!幸运的是,TPL库可以以非常简单和优雅的方式解决这个问题。CancelToken是您所需要的:在端口打开时:while(x)varmyTask=_serialPort.BaseStream.ReadAsync(_serialBuffer,0,_bufferLength,cancelToken.Token);varbytesRead=awaitmyTask;...你的业务逻辑在这里...if((myTask.IsCanceled)||(myTask.IsFaulted))break;}关闭端口:cancelToken.Cancel(false);注意while循环比递归调用好,因为当端口广播很多信息时,15分钟后会抛出栈溢出异常。这是一个非常简单的实现。我希望它有所帮助。以上就是C#学习教程:停止Stream.BeginRead()全部内容分享。代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: