当前位置: 首页 > news >正文

c#websocket心跳包自定义实现,支持异步操作的取消

public async Task StartAsync(){_cancellationTokenSource = new CancellationTokenSource();CancellationToken token = _cancellationTokenSource.Token;_heartbeatManager.StartHeartbeatService(token);
为什么要传TOKEN

在 C# 中,将CancellationToken传递给StartHeartbeatService方法是为了支持异步操作的取消。这是一种常见的模式,用于在需要时优雅地终止长时间运行的任务(如心跳服务)。

为什么需要传递 CancellationToken?

  1. 协作式取消机制
    C# 中的异步操作不会被强制终止,而是通过协作式取消实现。CancellationToken是一个令牌,允许你请求取消操作,而具体的操作逻辑需要检查这个令牌并决定如何响应。

  2. 避免资源泄漏
    如果心跳服务是一个周期性任务(如定时发送 Ping 包),不提供取消机制会导致任务持续运行,即使应用程序已经准备关闭。这可能导致资源泄漏或异常行为。

  3. 与其他异步操作保持一致
    遵循.NET 的最佳实践,长时间运行的异步方法应该接受CancellationToken参数,以便与其他异步 API(如Task.WhenAnyTask.Delay等)协同工作。

示例:心跳服务如何使用 CancellationToken

假设StartHeartbeatService的实现如下:csharp

public async Task StartHeartbeatService(CancellationToken cancellationToken)
{while (!cancellationToken.IsCancellationRequested){try{// 发送心跳包await SendHeartbeatAsync();// 等待指定间隔后再次发送await Task.Delay(HeartbeatInterval, cancellationToken);}catch (OperationCanceledException){// 任务被取消,正常退出Console.WriteLine("心跳服务已取消");}catch (Exception ex){// 处理其他异常Logger.LogError(ex, "心跳服务异常");}}
}

调用方如何触发取消?

在你的代码中,_cancellationTokenSource是一个类成员变量,因此可以在其他方法中触发取消:

// 启动服务
public async Task StartAsync()
{_cancellationTokenSource = new CancellationTokenSource();await _heartbeatManager.StartHeartbeatService(_cancellationTokenSource.Token);
}// 停止服务
public void Stop()
{_cancellationTokenSource?.Cancel();_cancellationTokenSource?.Dispose();_cancellationTokenSource = null;
}

最佳实践

  1. 传递令牌到所有子操作
    如果StartHeartbeatService内部调用其他支持取消的异步方法(如Task.DelayHttpClient.SendAsync),应将令牌传递给它们,确保整个操作链都能响应取消请求。

  2. 定期检查令牌状态
    在循环或长时间运行的操作中,定期检查cancellationToken.IsCancellationRequested,以便在没有等待操作时也能响应取消。

  3. 异常处理
    捕获OperationCanceledException以优雅地处理取消请求,避免将其视为错误。

总结

传递CancellationToken的目的是让心跳服务能够:

  • 在应用程序关闭时安全停止。
  • 在需要时(如检测到连接断开)主动终止。
  • 避免资源泄漏和孤儿任务。

这是实现可取消异步操作的标准做法,是编写健壮、可维护代码的关键。

http://www.lqws.cn/news/480331.html

相关文章:

  • C++——继承
  • 7.4.1_1B树
  • 从零开始手写redis(16)实现渐进式 rehash map
  • 《福格行为模型》
  • 鲲鹏服务器创建Zookeeper镜像实例
  • 【LLIE专题】NTIRE 2025 低照度图像增强第一名方案解读
  • C#设计模式-Builder-生成器-对象创建型模式
  • 编程江湖-设计模式
  • CentOS7中源码编译安装freeswitch
  • [project-based-learning] 开源贡献指南 | 自动化链接验证 | Issue模板规范
  • 系统思考:救火先放火
  • 详解Redis数据库和缓存不一致的情况及解决方案
  • sc4336p硬件设计上电时序
  • DeepSeek技术解析:开源大模型的创新突围之路
  • 基于Python Websockets的客户端程序,能够连接服务端、处理ping/pong、发送订阅请求并保持长连接
  • 《算法笔记》之二(笔记)
  • 基于split-Bregman算法的L1正则化matlab仿真,对比GRSR算法
  • RA4M2开发IOT(8)----IIC驱动OLED
  • 分库分表下的 ID 冲突问题与雪花算法讲解
  • Qt项目,记事本
  • YOLOv8/11自定义seg分割数据集格式转换json2txt
  • 第八章 目录一致性协议 A Primer on Memory Consistency and Cache Coherence - 2nd Edition
  • 如何用AI开发完整的小程序<10>—总结
  • unity版本控制PlasticSCM转git
  • 需求初步探讨-从OR-AR
  • 《Redis》事务
  • 抽象工厂设计模式
  • 查询消耗 IO 多的 SQL -达梦
  • 一个免费的视频、音频、文本、图片多媒体处理工具
  • 数据库高性能应用分析报告