C#中使用 async await TaskCompletionSource<T>实现异步逻辑同步写

Task、async 和 await 是 C# 中用于处理异步编程的关键概念。它们一起构成了异步编程的基础。

Task

Task 是表示异步操作的抽象,它属于 System.Threading.Tasks 命名空间。Task 可以表示已经完成的任务、正在运行的任务或者尚未开始的任务。通过 Task,可以执行异步操作、并发操作,以及异步等待任务完成。

async 和 await

async 和 await 关键字是异步编程的基础构造,用于简化异步代码的编写。它们通常一起使用,使得编写异步代码更加直观、易读。

async

关键字用于定义一个异步方法。异步方法可以包含 await 操作符,并且在异步执行期间可以被挂起,而不会阻塞调用线程。

await

await 操作符用于等待异步操作完成,并返回异步操作的结果。在 async 方法中,await 会将控制权返回给调用者,而不会阻塞线程,从而提高了程序的响应性。

TaskCompletionSource

TaskCompletionSource 是用于创建和控制 Task 实例的一种灵活的方式。通常情况下,Task 表示一个异步操作的结果,而 TaskCompletionSource 则允许你手动控制异步操作的完成。
tcs.SetResult(42) 来设置异步操作的结果
tcs.SetCanceled() 异步取消
tcs.SetException() 异常
TaskCompletionSource 成为一种强大的工具,用于自定义异步操作的实现和控制。

例子 直接上结果

在这里插入图片描述
以往的代码实现上都是请求一个异步操作挂载一个回调方法
使用Task可以轻松实现异步操作同步写代码

public class LoginLogic
{public async static void Call(){C2S_Login c2S_Login = new C2S_Login(){name = "wukong",password = "123456",};S2C_Login s2C_Login = await TaskLogic.Instance.Call<S2C_Login>(c2S_Login);Debug.LogError($"接收消息, id: {s2C_Login.id}, time: {s2C_Login.time}, location: {s2C_Login.location}");//这里直接处理后续逻辑}
}public class Test : MonoBehaviour
{void Start(){LoginLogic.Call();}
}

代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using System;
using System.Threading;namespace Game
{public interface IResponse{public int id { get; set; }}public interface IRequest{public int id { get; set; }}public class C2S_Login : IRequest{public int id { get; set; }public string name;public string password;}public class S2C_Login : IResponse{public int id { get; set; }public int time;public string token;public string location;}public class RPCInfo : IDisposable{public int id;public TaskCompletionSource<IResponse> tcs;public CancellationTokenSource cts;public void SetResult(IResponse response){tcs?.SetResult(response);}public void Dispose(){cts?.Dispose();}}public class TaskLogic{private static TaskLogic _instance;private int _id;private Dictionary<int, RPCInfo> _rpcs;//单位毫秒private const int RPC_TIMEOUT = 5000;public static TaskLogic Instance{get{if (_instance == null)_instance = new TaskLogic();return _instance;}}public TaskLogic(){Init();}public string GetName(){return "TaskLogic";}public bool Init(){_rpcs = new Dictionary<int, RPCInfo>();return true;}private async void Send(IRequest request){await Task.Run(async () =>{//这段代码只是用于模拟发送C2S_Login c2S_Login = request as C2S_Login;Debug.LogError($"发送消息, Name: {c2S_Login.name}, password: {c2S_Login.password}");//延迟一秒await Task.Delay(2000);//模拟接收S2C_Login s2C_Login = new S2C_Login(){id = request.id,time = DateTime.Now.Millisecond,location = "北京",};Recv(s2C_Login);});}public async Task<T> Call<T>(IRequest request) where T : class, IResponse, new(){Interlocked.CompareExchange(ref _id, 0, int.MaxValue);request.id = Interlocked.Increment(ref _id);//1.模拟一下发消息, 延迟1秒后调用回复Send(request);//2.等待消息返回IResponse response = await WaitTask(request);return response as T;}private Task<IResponse> WaitTask(IRequest request){TaskCompletionSource<IResponse> tcs = new TaskCompletionSource<IResponse>();CancellationTokenSource cts = new CancellationTokenSource();cts.CancelAfter(RPC_TIMEOUT);cts.Token.Register(() =>{Debug.LogError($"time out: {request}");_rpcs.Remove(request.id);});RPCInfo rpcInfo = new RPCInfo() { id = request.id, tcs = tcs, cts = cts };_rpcs.Add(request.id, rpcInfo);return rpcInfo.tcs.Task;}private void Recv(IResponse response){RPCInfo rpcInfo;if (!_rpcs.TryGetValue(response.id, out rpcInfo))return;rpcInfo.Dispose();rpcInfo.SetResult(response);_rpcs.Remove(response.id);}public void UnInit(){}public void Update(){}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8.spring validatation 原理

目录 概述实践理清脉络关键类总结源码调试实例关键断点如何生成校验结束概述 本文将对 spring validatation 如行进行校验,进行详细的说明。 此篇是对 仿若依后端系统业务实践 中校验模块,进行补充。 通过此篇,达到以下两个目标 达到对 spring validatation 全面总结理解 …

math.isnan()方法的理解

math.isnan() 是 Python 中 math 模块提供的函数之一&#xff0c;用于检查一个值是否为 NaN&#xff08;Not a Number&#xff09;。NaN 是一种特殊的浮点数值&#xff0c;表示一个未定义或不可表示的数值&#xff0c;通常在数学运算中涉及到无效的操作时会产生。 具体…

vue3如何用了按需引入组件如何修改ant的主题颜色

前言&#xff1a;按照网上修改主题颜色的方法一直都不生效 后来发现是引入了按需加载组件unplugin-auto-import 按照一下修改方式生效了 export default defineConfig({plugins: [vue(),// antd按需引入Components({resolvers: [AntDesignVueResolver({importStyle: "le…

你的第一个C/S程序

目录 socket服务端代码客户端代码执行结果 socket socket基础知识 服务端代码 import socket import threading import timeMSG_LENGTH 64 DISCONNECTED !CONNECTION CLOSED connections 0#定义服务器地址 server_ip socket.gethostbyname(socket.gethostname()) server…

【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

文章目录 一. 进行面向对象设计1. 划分职责>需要有哪些类2. 定义类及其属性和方法3. 定义类与类之间的交互关系4. 将类组装起来并提供执行入口 二. 如何进行面向对象编程&#xff1f;1. 接口实现2. 辩证思考与灵活应用 【设计模式之美】面向对象分析方法论与实现&#xff08…

教育场景数字化中音视频小程序的发展

教育场景数字化逐步成为刚需 2018年以来&#xff0c;国家对在线教育行业的监管收紧&#xff0c;以及受益于 5G 技术的发展&#xff0c;教育科技逐步走向成熟化和规范化。 教育行业的本质是人与人&#xff08;老师与学生、老师与家长&#xff0c;以及更多角色直接的沟通与互动…

中巴经济走廊沿线上游冰川冰湖相关灾害(事件)数据集

摘要 中巴经济走廊横穿现代冰川广泛分布的喀喇昆仑山和部分帕米尔山区,上游冰川动态及其演化导致的各类冰川相关灾害(冰川洪水/泥石流、冰川跃动、冰缘崩塌/滑坡以及冰川阻塞湖溃决洪水等)在众多山地灾害中尤其突出,对中巴公路及其沿线基础设施、人类活动日益构成威胁。本…

【数据结构和算法】小行星碰撞

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 什么情况会用到栈 2.2 方法一&#xff1a;模拟 栈 三、代码 3.1 方法一&#xff1a;模拟 栈 四…

【LLM+RS】LLM在推荐系统的实践应用(华为诺亚)

note LLM用于推荐主要还是解决推荐系统加入open domain 的知识。可以基于具体推荐场景数据做SFT。学习华为诺亚-技术分享-LLM在推荐系统的实践应用。 文章目录 note一、背景和问题二、推荐系统中哪里使用LLM1. 特征工程2. 特征编码3. 打分排序 三、推荐系统中如何使用LLM四、挑…

共享WiFi贴项目加盟可以解决商家哪些痛点?

近年来&#xff0c;共享WiFi贴项目在共享商业领域引起了广泛关注。作为一种便捷的网络分享工具&#xff0c;共享WiFi贴不仅受到很多人的青睐&#xff0c;更能够为商家带来诸多实际利益。那么&#xff0c;共享WiFi贴项目加盟究竟可以解决商家哪些痛点呢&#xff1f; 共享WiFi贴为…

【C#】知识点实践序列之Lock的锁定代码块

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂之知识点实践序列》文章。 2024年第1篇文章&#xff0c;此篇文章是C#知识点实践序列之Lock知识点&#xff0c;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 本篇验证Lock锁定代…

Navicat(数据库可视化软件)安装教程以及连接MYSQL

Navicat安装教程以及连接MYSQL Navicat&#xff08;数据库可视化软件&#xff09;安装流程安装MySQLnavicat连接mysql数据库 Navicat&#xff08;数据库可视化软件&#xff09; Navicat 是一款专门为 MySQL 设计的可视化数据库 GUI 管理工具&#xff0c;我们可以在自己的计算机…

深入浅出Python日志打印

0.引言 在编程过程中&#xff0c;日志记录是一项非常重要的任务&#xff0c;无论是用于调试代码、记录系统运行状态&#xff0c;还是跟踪可能出现的问题&#xff0c;日志都能发挥重要作用。然而&#xff0c;许多开发者习惯使用简单的print语句来记录信息&#xff0c;这种方法虽…

Qt的三大机制(面试)

Qt三大核心机制是信号与槽机制、事件机制和对象模型。 信号与槽机制&#xff1a;Qt中的信号与槽机制是一种用于对象间通信的机制。一个对象可以通过发出信号来通知其他对象&#xff0c;其他对象可以通过槽函数来响应该信号。信号与槽可以跨越不同的线程&#xff0c;实现了对象…

AI:105-基于深度学习的手术操作监控与辅助

🚀点击这里直接跳转到本专栏,可查阅顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

向爬虫而生---Redis 基石篇4 <拓展Set>

前言: 延伸上一篇:https://blog.csdn.net/m0_56758840/article/details/135349796 挖一挖集合的一些骚操作~ 正文: 基本操作: 集合是Redis中的一种数据类型&#xff0c;它具有以下几个基本概念和特性&#xff1a;无重复、无序和集合间的运算。下面是几个常用的集合命令&…

ensp vlan连接(详细)

1.将需要的设备放置好 2.将设备连接起来 3.启动所有设备 4.备注好每台PC机的信息 5.配置好每台PC机 6.配置交换机1 进入配置视图&#xff0c;关闭信息提示 重命名设备 批量创建VLAN 开始配置接口 更改接口类型为ACCESS 将接口划分到对应的VLANN 配置下一个接口&#xff0c;步…

编译 nccl-tests 项目

1&#xff0c;编译 下载源代码 git clone --recursive https://github.com/NVIDIA/nccl-tests.git 编译源代码 cd nccl-tests/ make -j 2&#xff0c;运行 cd ./build/ ./all_reduce_perf --help ./all_reduce_perf -b 8 -e 256M -f 2 -g 4 效果图&#xff1a; 3&#…

说说产品经理能力模型

产品经理的能力模型应该是什么样的&#xff0c;可能100个产品人会有100种看法&#xff0c;每个人的认知都是不一样的&#xff0c;今天和大家分享下我对产品经理能力模型的总结。 前段时间&#xff0c;一个30多岁做前端开发的朋友跟我说想转行做产品&#xff0c;让我帮忙指导下…

四种限流算法

四种限流算法 为什么要限流 限流是为了防止系统突然收到大量请求&#xff0c;后台面对大量并发请求对cpu和内存&#xff0c;网络io产生巨大压力&#xff0c;可能将一些服务如mysql&#xff0c;redis等打崩&#xff0c;引发系统故障&#xff0c;服务瘫痪。 固定窗口&#xff…