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

【SuperSocket 】利用 TaskCompletionSource 在 SuperSocket 中实现跨模块异步处理客户端消息

利用 TaskCompletionSource 在 SuperSocket 中实现跨模块异步处理客户端消息

在使用 SuperSocket 构建 TCP 服务时,我们经常会遇到这样的需求:

  • 服务端接收到客户端数据后,需要将数据交给其他模块处理
  • 处理完成后再将结果返回给调用模块或客户端
  • 希望调用模块能够异步等待处理结果,而不是阻塞线程

本文将通过 TaskCompletionSource 来实现这一场景,并结合 SuperSocket 的异步回调机制,讲解完整实现方法。


1️⃣ TaskCompletionSource 基础语法

TaskCompletionSource<T>(简称 TCS)是 .NET 中用于手动控制 Task 完成时机的工具。

1.1 基本概念

  • Task:异步操作的表示,通常由方法内部执行完成
  • TaskCompletionSource:你可以手动控制 Task 何时完成,以及完成结果是什么
var tcs = new TaskCompletionSource<int>();
Task<int> task = tcs.Task;// 模拟异步事件
Task.Run(async () =>
{await Task.Delay(1000);   // 模拟耗时操作tcs.SetResult(42);        // 手动完成 Task 并返回结果
});int result = await task;
Console.WriteLine(result);    // 输出 42

核心思想:TaskCompletionSource 就像一个“空盒子”,你自己决定什么时候放入结果并“打开盒子”。


1.2 TCS 常用方法

方法功能
SetResult(T result)设置 Task 成功完成并返回结果
TrySetResult(T result)安全写法,如果 Task 已完成不会抛异常
SetException(Exception ex)设置 Task 异常完成
SetCanceled()取消 Task

2️⃣ 在 SuperSocket 中使用 TCS

SuperSocket 的核心是事件驱动,客户端数据到达时会触发 UsePackageHandler 回调。我们可以利用 TCS,将“事件”转换为“可 await 的 Task”,实现异步等待消息。


2.1 定义等待方法

在服务端或调用模块中定义:

private TaskCompletionSource<int> _tcs;public Task<int> WaitForNextPackageAsync()
{_tcs = new TaskCompletionSource<int>();return _tcs.Task; // 返回可 await 的 Task
}
  • 外部模块调用 await WaitForNextPackageAsync() 时,会挂起等待
  • 直到 _tcs.SetResult(result) 被触发

2.2 接收客户端消息并触发 TCS

public event Func<StringPackageInfo, Task<int>> OnPackageReceived;private async ValueTask HandlePackageAsync(IAppSession session, StringPackageInfo package)
{int result = 0;// 调用外部模块处理消息if (OnPackageReceived != null){result = await OnPackageReceived.Invoke(package);}// 完成 TaskCompletionSource,将结果返回给等待方_tcs?.TrySetResult(result);// 同时可以给客户端发送响应await session.SendAsync(Encoding.UTF8.GetBytes(result.ToString() + "\r\n"));
}

这里实现了 消息接收与处理逻辑解耦

  • SuperSocket 只负责接收消息
  • 外部模块处理业务逻辑
  • 调用模块异步等待处理结果

2.3 外部模块处理逻辑示例

mainWindow.OnPackageReceived += async (package) =>
{int result = 0;switch (package.Key.ToUpper()){case "ADD":result = package.Parameters.Select(int.Parse).Sum();break;case "SUB":result = package.Parameters.Select(int.Parse).Aggregate((x, y) => x - y);break;case "MULT":result = package.Parameters.Select(int.Parse).Aggregate((x, y) => x * y);break;}return result; // 返回给 TaskCompletionSource
};

2.4 调用模块等待结果

int result = await mainWindow.WaitForNextPackageAsync();
Console.WriteLine($"处理结果: {result}");
  • 外部模块就像同步等待一样获得了处理结果
  • 实际上整个流程是 异步、非阻塞

3️⃣ 支持多客户端或多条命令

如果有多个客户端或希望同时处理多条消息,可以使用 队列管理 TCS

private ConcurrentQueue<TaskCompletionSource<int>> _queue = new();public Task<int> WaitNextAsync()
{var tcs = new TaskCompletionSource<int>();_queue.Enqueue(tcs);return tcs.Task;
}private async ValueTask HandlePackageAsync(IAppSession session, StringPackageInfo package)
{int result = CalculateResult(package);if (_queue.TryDequeue(out var tcs))tcs.TrySetResult(result);await session.SendAsync(Encoding.UTF8.GetBytes(result.ToString() + "\r\n"));
}
  • 每条消息对应一个 TCS
  • 保证多客户端/多命令都能异步等待结果

4️⃣ 总结

把回调变成了异步等待,这个真的是太酷啦~~~~~~~

通过 TaskCompletionSource,我们可以:

  1. 将事件驱动转为可 await 的异步操作
  2. 实现跨模块异步处理客户端消息
  3. 保持服务端与业务逻辑解耦
  4. 同时支持客户端响应和模块异步等待

核心模式:
HandlePackageAsync 触发 → 外部模块处理 → TaskCompletionSource.SetResult → 调用模块 await 获取结果

这种模式非常适合 SuperSocket、SignalR、WebSocket 等异步消息驱动场景。


文章转载自:

http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://00000000.cknrs.cn
http://www.dtcms.com/a/367809.html

相关文章:

  • 2025前端面试题及答案(详细)
  • 深度学习篇---pytorch数据集
  • 数据结构之单链表和环形链表的应用(二)-
  • 第二阶段WinForm-12:UI控件库
  • 题解 洛谷P13778 「o.OI R2」=+#-
  • 从零到一:人工智能应用技术完全学习指南与未来展望
  • 用遗传算法破解一元函数最大值问题:从原理到 MATLAB 实现
  • 后端Long类型数据传给前端造成精度丢失
  • 2025年GEO优化公司:AI驱动的增长新引擎——权威深度解析与遴选指南
  • Redis是单线程的,为啥那么快呢?经典问题
  • 【Python】数据可视化之核密度
  • 从传统CNN到残差网络:用PyTorch实现更强大的图像分类模型
  • 【DINOv3教程2-热力图】使用DINOv3直接生成图像热力图【附源码与详解】
  • 追觅极境冰箱震撼上市:以首创超低氧保鲜科技打造家庭健康中心
  • n8n中文版部署步骤说明
  • Leetcode 876. 链表的中间结点 快慢指针
  • JavaSe之多线程
  • java程序员的爬虫技术
  • CPU设计范式(Design Paradigms)有哪些?
  • MVCC是如何工作的?
  • springboot在线投票系统(代码+数据库+LW)
  • 如何设计用户在线时长统计系统?
  • timm==0.5.4 cuda=11.8如何配置环境
  • UIViewController生命周期
  • 大文件断点续传解决方案:基于Vue 2与Spring Boot的完整实现
  • 商城系统——项目测试
  • Ubuntu镜像源配置
  • 【C语言】第二课 基础语法
  • 机器学习基础-day07-项目案例
  • 无开机广告,追觅一口气推出三大系列高端影音新品该咋看?