非异步方法中Task.ContinueWith的性能与使用异步/等待的性能 [英] Performance of Task.ContinueWith in non-async method vs. using async/await

查看:238
本文介绍了非异步方法中Task.ContinueWith的性能与使用异步/等待的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose you have a method that wraps an inner long-running method. This outer method may do a tiny amount of work before/after calling said long-running method. For example:

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

使用async生成的样板代码的附加重量似乎不一定值得使用await的好处,因为它的延续基本上是微不足道的.因此,在给定足够小的连续性的情况下,使用Task.ContinueWith是否更有效?例如

It seems like the added weight of the boilerplate code generated by using async is not necessarily worth the benefit of using await, since its continuation is basically trivial. Therefore, given a sufficiently trivial* continuation, is it more performant to use Task.ContinueWith? E.g.

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

* 是的,足够"和琐碎"都是模糊的术语.另外,在这个人为的示例中,我也忽略了异常处理.我认为需要处理异常意味着继续是不平凡的.

* Yes, both 'sufficiently' and 'trivial' are vague terms. Also, I've ignored exception handling in this contrived example. I suppose the need to handle exceptions implies that the continuation is non-trivial.

推荐答案

因此,给定足够小的连续性,使用Task.ContinueWith是否更具性能?

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

是的,但我认为这是一个错误的问题.

Yes, but I argue that this is the wrong question to ask.

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

It is more performant. However, you have to be very careful to handle edge cases (in particular, any exceptions raised by LongRunningAsync would get wrapped in an AggregateException by your code). In addition, await will capture a context by default, and resume the method in that context. You can handle special cases in a more performant way via ContinueWith, but you can't handle the general case in a more performant way.

但是无论如何,性能是一个错误的问题.我认为要问的一个更好的问题是:Is the code sufficiently performant, and if so, which solution is more maintainable?

But performance is the wrong question to ask anyway. I argue that a better question to ask is: Is the code sufficiently performant, and if so, which solution is more maintainable?

考虑代码将执行多少次.百万?将节省多少时间?几纳秒? ContinueWith方法需要多少开发人员时间?每当有人看代码时,要花更长的时间才能看到它在做什么.通过使代码更具可维护性(集中节省您的公司资金)来节省开发人员时间,这远比节省绝对少得多的决定要好得多.代码运行的时间(将节省的费用分散到所有客户端上-并将其分散到很小的范围内,甚至没有一个客户端会意识到这一点).

Consider how many times the code will be executed. Millions? How much time will be saved? A few nanoseconds? How much developer time with the ContinueWith approach cost? Every time anyone looks at the code, it takes that much longer to see what it's doing. It is a far, far better decision to save developer time by making the code more maintainable (concentrating the savings in your company) than it is to save an absolutely minuscule amount of time when the code is run (spreading the savings across all your clients - and spreading it so thin that no single client will even be aware of it).

这篇关于非异步方法中Task.ContinueWith的性能与使用异步/等待的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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