如何不使用异步状态机将Task包装为Task<TResult>?
非异步方式将Task包装为Task的无错误实现
可以通过TaskCompletionSource<T>实现完全符合要求的非异步包装方案,无需生成异步状态机,同时严格保留原Task的核心属性:
Task<T> ConvertToTaskOfT<T>(Task task, T result) { if (task == null) throw new ArgumentNullException(nameof(task)); var tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously); // 先处理任务已完成的场景,避免多余的延续注册 switch (task.Status) { case TaskStatus.RanToCompletion: tcs.SetResult(result); break; case TaskStatus.Faulted: tcs.SetException(task.Exception.InnerExceptions); break; case TaskStatus.Canceled: tcs.SetCanceled(); break; default: // 任务未完成时,注册延续同步状态 task.ContinueWith(t => { switch (t.Status) { case TaskStatus.RanToCompletion: tcs.SetResult(result); break; case TaskStatus.Faulted: tcs.SetException(t.Exception.InnerExceptions); break; case TaskStatus.Canceled: tcs.SetCanceled(); break; } }, TaskContinuationOptions.ExecuteSynchronously); break; } return tcs.Task; }
符合要求的验证说明
- 状态完全同步:无论是原Task已完成还是未完成,都会直接将其状态同步到
TaskCompletionSource生成的Task<T>中,返回对象的Status属性与原Task完全一致。 - Exception属性一致:原Task故障时,直接传递其
Exception.InnerExceptions给SetException方法,确保返回的Task<T>的Exception属性与原Task完全相同。 - 无阻塞异步执行:通过
Task.ContinueWith注册的延续操作会在原Task完成时异步触发,不会阻塞当前线程;TaskCreationOptions.RunContinuationsAsynchronously参数确保后续绑定到返回Task<T>的延续也会异步执行,彻底避免阻塞。
内容的提问来源于stack exchange,提问作者Ivan Petrov
相关产品推荐
相关产品推荐

