如何关闭Swagger时调用TCP连接类Dispose方法清理套接字
解决Swagger终止微服务时TCP类Dispose未触发的问题
1. 先规范IDisposable实现
确保你的TCP类正确实现IDisposable模式,覆盖托管/非托管资源的清理,避免套接字残留:
public class TcpConnection : IDisposable { private Socket _socket; private bool _disposed; // 业务逻辑代码 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { // 先关闭套接字的收发通道 _socket?.Shutdown(SocketShutdown.Both); } // 强制关闭套接字,释放底层资源 _socket?.Close(); _socket = null; _disposed = true; } ~TcpConnection() => Dispose(false); }
2. 绑定ASP.NET Core应用生命周期钩子
微服务基于ASP.NET Core托管时,通过应用生命周期事件主动触发Dispose,覆盖Swagger窗口关闭的场景:
方式一:注册ApplicationStopping回调
在Program.cs中注入IHostApplicationLifetime,监听应用停止信号:
var builder = WebApplication.CreateBuilder(args); // 注册你的TCP类为单例/作用域服务 builder.Services.AddSingleton<TcpConnection>(); var app = builder.Build(); var lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>(); var tcpConn = app.Services.GetRequiredService<TcpConnection>(); // 应用停止前触发Dispose lifetime.ApplicationStopping.Register(() => tcpConn.Dispose()); // Swagger配置 app.UseSwagger(); app.UseSwaggerUI(); app.Run();
方式二:封装为IHostedService
如果TCP类需要长期维持连接,包装成IHostedService,让主机自动管理启停:
public class TcpHostedService : IHostedService, IDisposable { private readonly TcpConnection _tcpConn; public TcpHostedService(TcpConnection tcpConn) { _tcpConn = tcpConn; } public Task StartAsync(CancellationToken cancellationToken) { // 初始化TCP连接逻辑 return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { // 应用停止时自动调用Dispose _tcpConn.Dispose(); return Task.CompletedTask; } public void Dispose() => _tcpConn.Dispose(); }
然后在Program.cs中注册托管服务:
builder.Services.AddHostedService<TcpHostedService>(); builder.Services.AddSingleton<TcpConnection>();
3. 处理强制终止场景
如果关闭Swagger窗口是直接杀死进程(比如任务管理器结束进程),托管代码的清理逻辑无法执行,此时依赖TCP套接字的系统级配置:
// 在Socket初始化时设置SO_LINGER选项 var lingerOpt = new LingerOption(true, 5); // 5秒超时 _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOpt);
开启该选项后,进程终止时操作系统会在超时时间内主动发送FIN包,强制关闭连接,减少ESTABLISHED状态的残留。
4. 局部实例用using包裹
如果TCP类是业务方法中的局部实例,必须用using语句确保即时释放:
using(var tcpConn = new TcpConnection()) { // 执行TCP通信逻辑 }
内容的提问来源于stack exchange,提问作者Dominique
相关产品推荐
相关产品推荐

