You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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");
}

问题分析与解决建议

  1. 避免使用静态字段存储TcpClient:MAUI页面的静态字段可能因页面导航、GC回收等被意外置空,改用实例字段存储传入的TcpClient对象,保证对象生命周期与页面一致。
  2. 用using自动管理流生命周期:创建StreamWriter和StreamReader时直接用using语句,无需手动调用Close,自动完成资源释放:
    using var stream = client.GetStream();
    using var writer = new StreamWriter(stream);
    using var reader = new StreamReader(stream);
    
  3. 先检查对象非空再执行关闭操作:client.Connected是即时状态快照,无法完全反映当前连接有效性,关闭前先判断对象是否为空:
    if (client != null)
    {
        Writer?.Flush();
        Writer?.Dispose();
        Reader?.Dispose();
        client.Close();
        client.Dispose();
    }
    
  4. 优化对象传递方式:避免页面间直接传递TcpClient,可通过App类的全局属性或依赖注入存储对象,防止传递过程中被意外回收。

内容的提问来源于stack exchange,提问作者Алексей Кондратьев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:37:29