基于任务的异步模式和基于事件/回调的异步模式
问题场景描述
web api:需要向另一个服务器发送http请求,等待服务器的回调结果,若指定时间内比如10分钟没有收到回调则返回失败,否则处理回调返回。
典型的基于时间/回调的异步模式,和经常使用的await 模式不同,async/await是基于任务的异步模式,任务完成返回。而前面这种应用场景依赖回调处理结果或时间,不是简单地等待一段时间,等待的时间还要根据回调进行后续操作。
C#实现基于事件/回调的异步模式
1.TaskCompletionSource<T>
它允许你手动控制一个 Task<T>
的完成状态。这在你需要将基于回调的异步模式转换为基于任务的异步模式时特别有用。这样,你就可以使用 async/await 语法,而不是处理更复杂的回调或事件模式。它通过提供一个与 Task
相关联的方式来创建、完成、取消或失败一个任务,使得将基于事件或回调的异步模式适配到基于任务的异步模式变得简单。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestTaskCompletionSource { internal class PerformOperation { // 假设的基于回调的异步操作 void PerformOperationAsync(Action<int> onSuccess, Action<Exception> onError) { // 这里模拟异步操作 Thread.Sleep(1000); // 假装我们在这里做了一些异步工作 onSuccess(42); // 假设操作成功,并返回了结果 } // 使用 TaskCompletionSource 封装上面的方法 Task<int> PerformOperationAsync() { var tcs = new TaskCompletionSource<int>(); PerformOperationAsync( result => tcs.SetResult(result), error => tcs.SetException(error)); //lamberda表达式本质就是匿名函数,传递的是委托 return tcs.Task; } // 使用新的基于任务的异步方法 public async Task UseOperationAsync() { try { int result = await PerformOperationAsync(); Console.WriteLine($"操作成功,结果为:{result}"); } catch (Exception ex) { Console.WriteLine($"操作失败:{ex.Message}"); } } } }
2.实现原理
3.源码解析
F:\LearnTest\csharp\TestTaskCompletionSource