我正在实现异步的接口方法(返回Task)。但是,我的实现必然是同步的。最好的方法是什么?有没有一些内置的方法来做到这一点?以下是我考虑的几个选项:
选项1:Task.FromResult
return Task.FromResult(ComputeResult());
这很好,因为我的代码同步运行。缺点是如果ComputeResult()失败或被取消,我的方法抛出而不是返回失败的任务。
选项2:Task.Run
return Task.Run(() => ComputeResult());
这更自然地传播失败和取消。但是,这也引入了不必要的线程跳。
选项3:TaskCompletionSource
var tcs = new TaskCompletionSource<T>();
try
{
tcs.SetResult(ComputeResult());
}
catch (OperationCanceledException)
{
tcs.SetCanceled();
}
catch (Exception ex)
{
tcs.SetException(ex);
}
return tcs.Task;
这会传播失败/取消并避免线程跳跃,但它更冗长和复杂。
答案 0 :(得分:2)
您可能忽略了另外两个选项:
只需制作您的方法async
并执行return ComputeResult()
即可。使用pragma
抑制编译器警告。如果你不想取消警告,你可以这样做:
async Task<Result> ComputeResultAsync()
{
await Task.FromResult(0);
return ComputeResult();
}
使用Task.RunSynchronously
:
Task<Result> ComputeResultAsync()
{
var task = new Task<Result>(() => ComputeResult());
task.RunSynchronously(TaskScheduler.Default);
return task;
}
后者将提供类似于async
方法的异常传播。但请注意,under certain conditions(就像它在堆栈上太深时),RunSynchronously
仍然可以异步执行。