Android平台MAUI应用中TcpClient对象无法正常关闭问题
问题描述
我有两个应用:服务端是C#控制台程序,基于TcpClient实现连接监听逻辑,通过StreamWriter和StreamReader完成消息读写;客户端是Android平台的MAUI应用,拆分多个页面实现登录、欢迎、登出及消息发送功能。
客户端在某页面创建TcpClient对象并成功连接后,将其传入下一页。后续页面通过流与服务端收发消息,但尝试关闭流或TcpClient时,发现对象为空,可连接仍处于挂起状态。
相关代码
服务端代码
try { if (client.Connected) { message = await Reader.ReadLineAsync(); if (message == null) continue; message = $"{userName}: {message}"; Console.WriteLine(message); File.AppendAllText(path, message + Environment.NewLine); await server.BroadcastMessageAsync(message, Id); } else { throw new Exception(); } } catch { message = $"{userName} closed the connection"; Console.WriteLine(message); File.AppendAllText(path, message + Environment.NewLine); await server.BroadcastMessageAsync(message, Id); break; }
客户端第一页代码
public TcpClient client = new TcpClient(); try { using (var cts = new CancellationTokenSource()) { cts.CancelAfter(timeout); var connectTask = client.ConnectAsync(host, port); var completedTask = await Task.WhenAny(connectTask, Task.Run(() => cts.Token.WaitHandle.WaitOne())); if (completedTask == connectTask) { await connectTask; var chatPage = new ChatPage(client); Application.Current.MainPage = chatPage; } else { Application.Current.MainPage = new Disconnect(client); return; } } } catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionRefused) { Application.Current.MainPage = new Disconnect(client); client.Close(); return; }
客户端第二页代码
// 通过构造函数接收TcpClient对象,创建静态私有TcpClient client并赋值 if (client.Connected) { Writer?.Close(); Reader?.Close(); client.Close(); } else { DisplayAlert("Error", "ok", "оk"); }
问题分析与解决建议
- 避免使用静态字段存储TcpClient:MAUI页面的静态字段可能因页面导航、GC回收等被意外置空,改用实例字段存储传入的
TcpClient对象,保证对象生命周期与页面一致。 - 用
using自动管理流生命周期:创建StreamWriter和StreamReader时直接用using语句,无需手动调用Close,自动完成资源释放:using var stream = client.GetStream(); using var writer = new StreamWriter(stream); using var reader = new StreamReader(stream); - 先检查对象非空再执行关闭操作:
client.Connected是即时状态快照,无法完全反映当前连接有效性,关闭前先判断对象是否为空:if (client != null) { Writer?.Flush(); Writer?.Dispose(); Reader?.Dispose(); client.Close(); client.Dispose(); } - 优化对象传递方式:避免页面间直接传递
TcpClient,可通过App类的全局属性或依赖注入存储对象,防止传递过程中被意外回收。
内容的提问来源于stack exchange,提问作者Алексей Кондратьев
相关产品推荐
相关产品推荐

