调用AcceptTcpClient()后应用无响应,TCP服务端点击启动即冻结
问题根因
你在服务端的Startbutton_Click事件中直接运行了阻塞式TCP监听逻辑。WPF所有界面渲染、用户交互都依赖主线程(UI线程),以下操作直接占死了UI线程,导致界面完全无法响应:
listener.AcceptTcpClient()是阻塞方法,无客户端连接时会持续等待不返回- 后续的
stream.Read()也是阻塞方法,无数据接收时会持续等待 - 外层
while(true)死循环导致整个点击事件永远不会执行完成,UI线程全程被占用
修复方案
使用async/await异步改造服务端逻辑,将TCP操作放到后台线程执行,仅在更新界面时调度回UI线程,修改后代码如下:
// 方法增加async修饰符 private async void Startbutton_Click(object sender, RoutedEventArgs e) { try { listener = new TcpListener(localAddr, port); ChatScreentextBox.AppendText("waiting for connection...\n"); listener.Start(); Byte[] bytes = new Byte[256]; String data = null; // 后台运行监听逻辑,不阻塞UI线程 await Task.Run(async () => { while (true) { // 异步接收客户端连接 TcpClient client = await listener.AcceptTcpClientAsync(); data = null; NetworkStream stream = client.GetStream(); int i; while ((i = await stream.ReadAsync(bytes, 0, bytes.Length)) != 0) { data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); // UI更新必须调度回UI线程执行 Dispatcher.Invoke(() => { ChatScreentextBox.AppendText(data); }); data = data.ToUpper(); byte[] msg = System.Text.Encoding.ASCII.GetBytes(data); await stream.WriteAsync(msg, 0, msg.Length); Dispatcher.Invoke(() => { ChatScreentextBox.AppendText(data + "connection"); }); } client.Close(); } }); } catch (SocketException ex) { MessageBox.Show(ex.Message); } finally { listener.Stop(); } }
其他注意事项
- 客户端代码的
Connectbutton_Click方法中也存在stream.Read()阻塞调用,若后续需要实现持续收发功能,建议同步改成异步实现,避免客户端也出现卡顿 - 客户端代码中
ChatScreentextBox.AppendText(data + "\n");为错误写法:data是Byte数组,直接拼接字符串会输出类型名而非实际发送的内容,可修改为ChatScreentextBox.AppendText("hello\n"); - 多客户端连接场景下,建议每个接入的客户端单独分配异步任务处理收发,不要阻塞主监听逻辑
- 增加窗口关闭时的资源释放逻辑,主动停止监听、关闭所有已连接的Socket,避免端口占用问题
内容的提问来源于stack exchange,提问作者grif_noob
相关产品推荐
相关产品推荐

