如何利用回调完成任务?封装异步回调为Task返回结果的方法
将基于回调的异步操作封装为Task
要把这种回调式的异步方法封装成返回Task<bool>的形式,最标准的做法是用TaskCompletionSource<T>——它专门用来把传统回调模式转换为Task-based异步模式(TAP)。
实现步骤
- 创建
TaskCompletionSource<bool>实例,它相当于一个"任务控制器",可以手动控制Task的完成状态和返回结果。 - 定义内部回调函数,在这个回调里根据业务逻辑判断操作成功/失败,然后通过
TaskCompletionSource设置Task的结果。 - 调用原有的
MoveTo方法传入内部回调,最后返回TaskCompletionSource的Task属性。
完整代码示例
// 封装的异步方法 public static Task<bool> MoveToAsync(Device device, Position position) { var taskCompletionSource = new TaskCompletionSource<bool>(); // 定义内部回调,捕获taskCompletionSource void CommandCompleteCallback(ulong taskID) { try { // 这里替换成你实际判断任务成功/失败的逻辑 bool operationSucceeded = CheckTaskResult(taskID); // 用TrySetResult确保即使回调被多次触发也不会抛出异常 taskCompletionSource.TrySetResult(operationSucceeded); } catch (Exception ex) { // 如果回调执行中出现异常,将异常绑定到Task上 taskCompletionSource.TrySetException(ex); } } // 调用原方法传入回调 device.MoveTo(position, CommandCompleteCallback); // 返回Task,外部可以用await等待结果 return taskCompletionSource.Task; } // 示例:模拟判断任务结果的方法 private static bool CheckTaskResult(ulong taskID) { // 这里写你实际的判断逻辑,比如根据taskID查询设备状态等 return true; // 替换为真实结果 }
使用方式
封装完成后,就可以用异步/await语法来调用,代码更简洁易读:
// 在异步方法中调用 bool moveResult = await MoveToAsync(device, targetPosition); if (moveResult) { // 处理成功逻辑 } else { // 处理失败逻辑 }
注意事项
- 用
TrySetResult而非SetResult:如果设备的回调可能被意外多次触发,SetResult会抛出InvalidOperationException,TrySetResult会安全地忽略后续的设置操作。 - 异常处理:务必在回调内部捕获异常并通过
TrySetException绑定到Task,否则异常会在后台线程抛出,难以追踪。
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

