将同步代码包装为异步Task的最佳方法是什么? [英] What's the best way to wrap a synchronous code as an async Task?

查看:56
本文介绍了将同步代码包装为异步Task的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现异步的接口方法(返回Task).但是,我的实现必然是同步的.最好的方法是什么?有内置的方法可以做到这一点吗?我正在考虑以下几种选择:

I am implementing an interface method that is asynchronous (returns Task). However, my implementation is by necessity synchronous. What's the best way to do this? Is there some built-in way to do this? Here are several options I'm considering:

  • 选项1:Task.FromResult

  • Option 1: Task.FromResult

return Task.FromResult(ComputeResult());

这很好,因为我的代码是同步运行的.缺点是,如果ComputeResult()失败或被取消,我的方法将抛出异常,而不是返回失败的任务.

This is good because my code runs synchronously. The disadvantage is that if ComputeResult() fails or is canceled my method throws instead of returning a failed task.

  • 选项2:Task.Run

  • Option 2: Task.Run

return Task.Run(() => ComputeResult());

这更自然地传播故障和取消.但是,这也会引入不必要的线程跳动.

This propagates failure and cancellation more naturally. However, this also introduces an unnecessary thread-hop.

  • 选项3:TaskCompletionSource

  • Option 3: TaskCompletionSource

var tcs = new TaskCompletionSource<T>();
try 
{ 
    tcs.SetResult(ComputeResult()); 
}
catch (OperationCanceledException) 
{ 
    tcs.SetCanceled(); 
}
catch (Exception ex) 
{ 
    tcs.SetException(ex); 
}

return tcs.Task;

这既传播了失败/取消的信息,又避免了线程跳动,但是它更加冗长和复杂.

This both propagates failure/cancellation AND avoids the thread-hop, but it's more verbose and complex.

推荐答案

您可能会忽略的另外两个选项:

Two other options you might have overlooked:

  • 只需使您的方法 async 并执行 return ComputeResult().使用 pragma 禁止编译器警告.如果您不想抑制警告,则可以执行以下操作:

  • just make your method async and do return ComputeResult(). Suppress the compiler warning with pragma. If you don't like to suppress the warning, you could do this:

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 方法的异常传播.但是请注意,在某些条件下(例如太深了), RunSynchronously 仍然可以异步执行.

    The latter will provide exception propagation similar to the async method. Note however, under certain conditions (like when it's too deep on the stack), RunSynchronously could still execute asynchronously.

    这篇关于将同步代码包装为异步Task的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆