c# - Task.ContinueWith 在非异步方法中的性能与使用 async/await 的对比

标签 c# .net task-parallel-library async-await

假设您有一个包装内部长时间运行方法的方法。这个外部方法可能会在调用所述长时间运行的方法之前/之后做少量工作。例如:

public async Task<int> LongRunningWrapperAsync()
{
    int result = await LongRunningAsync();
    result++;
    return result;
}

似乎使用 async 生成的样板代码增加的重量并不一定值得使用 await,因为它的延续基本上是微不足道的。因此,给定一个足够微不足道的*延续,使用 Task.ContinueWith 是否更高效?例如

public Task<int> LongRunningWrapperAsync()
{
    return LongRunningAsync().ContinueWith(task => task.Result + 1,
                 TaskContinuationOptions.ExecuteSynchronously);
}

* 是的,“足够”和“微不足道”都是模糊的术语。此外,我在这个人为的示例中忽略了异常处理。我想处理异常的需要意味着延续是非常重要的。

最佳答案

Therefore, given a sufficiently trivial* continuation, is it more performant to use Task.ContinueWith?

是的,但我认为这是错误的问题。

它的性能更高。但是,您必须非常小心地处理边缘情况(特别是,LongRunningAsync 引发的任何异常都会被您的代码包装在 AggregateException 中)。此外,await 会默认捕获上下文,并在该上下文中恢复方法。您可以通过 ContinueWith 以更高效的方式处理特殊情况,但您无法以更高效的方式处理一般情况。

但无论如何,性能都是一个错误的问题。我认为一个更好的问题是:代码的性能是否足够好,如果是,哪种解决方案更易于维护?

考虑代码将被执行多少次。百万?将节省多少时间?几纳秒?使用 ContinueWith 方法需要花费多少开发人员时间?每次有人查看代码时,都需要更长的时间才能看到它在做什么。通过使代码更易于维护(将节省的资金集中在您的公司中)来节省开发人员时间远比节省绝对微不足道的时间要好得多代码运行的时间(将节省的费用分摊到所有客户 - 并且分摊得如此之薄,以至于没有一个客户甚至会意识到它)。

关于c# - Task.ContinueWith 在非异步方法中的性能与使用 async/await 的对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21403023/

相关文章:

.net - NuGet 限制包的最大主要版本

c# - 使用 Parallel.for 循环的文件 I/O 问题

收集结果的 C# ActionBlock 等价物

c# - Log4Net smtp appender 仅在出现完整日志(调试和信息和错误)错误时发送电子邮件。仅当应用程序结束时

c# - 在 WPF DataGrid 中均匀分布列

.net - 160 位 SHA1 散列的前 32 位是否可以替代 CRC32 散列?

c# - 如何修复具有 SynchronizationContext 的线程池线程上的死锁?

c# - 不知道类型时如何指定类型化变量

c# - 如何给泛型施加对引用类型的约束?

c# - 什么时候使用 C# ref 关键字是个好主意?