C#中NetworkStream.ReadAsync读取异常,仅调试模式下可用
问题分析与修复方案
核心问题
- 多余的
DataAvailable检查:你在循环里先判断networkStream.DataAvailable才调用ReadAsync,但ReadAsync本身会异步等待数据到来,不需要提前检查。当没有数据时,代码会进入无限空循环,占用CPU,且无法响应后续数据(甚至客户端断开连接时也无法退出循环)。单步调试时因为人工停顿,DataAvailable刚好为true,所以能进入ReadAsync执行。 async void的误用:async void仅适用于UI事件处理等场景,普通异步方法应该用async Task,否则无法跟踪方法执行状态,异常也无法被正确捕获。- 读取数据的字符串转换错误:直接使用
Encoding.ASCII.GetString(data)会把整个4096字节数组转成字符串,包括未被填充的空字节,应该用返回的result作为实际读取长度。 - 资源释放不规范:手动调用
Dispose存在异常风险,应该用using语句自动管理资源生命周期。
修复后的代码
public async Task ReadClientDataAsync(TcpClient tcpClient) { using (tcpClient) using (NetworkStream networkStream = tcpClient.GetStream()) { byte[] data = new byte[4096]; int result; while ((result = await networkStream.ReadAsync(data, 0, data.Length)) != 0) { string receivedText = System.Text.Encoding.ASCII.GetString(data, 0, result); Debug.WriteLine(receivedText); } Console.WriteLine("DONE"); } }
修复说明
- 移除
DataAvailable检查:让ReadAsync自然等待数据,避免空循环,客户端断开连接时,ReadAsync会返回0,循环正常退出。 - 改为
async Task:调用方可以通过await等待该方法完成,异常也能被捕获处理。 - 修正字符串转换:只转换实际读取的字节数,避免多余空字符。
- 使用
using语句:自动释放TcpClient和NetworkStream,无需手动调用Dispose,即使出现异常也能确保资源回收。
内容的提问来源于stack exchange,提问作者hamon
相关产品推荐
相关产品推荐

