返回Task的方法的不同实现

时间:2016-06-02 08:38:05

标签: c# asynchronous task-parallel-library

这是我在重构一些遗留代码时遇到的问题。

考虑一个返回Task的接口的方法:

public interface IFoo
{
    Task Bar();
}

Bar方法实现可以通过两种方式实现:

返回Task

public class Foo1 : IFoo
{
    public Task Bar()
    {
        return Task.Run(() =>
            {
                /* some work */
            });
    }
}

或使用async ... await

public class Foo2 : IFoo
{
    public async Task Bar()
    {
        await Task.Run(() =>
            {
                /* some work */
            });
    }
}

这些实现在功能上是等同的,还是存在(可能是微妙的)差异?

3 个答案:

答案 0 :(得分:2)

由于使用async-await语法会导致编译器生成在任务完成后实际继续通过await语句的代码,因此存在很大差异。此外,等待出现故障的任务会导致异常冒泡,这意味着它不再被视为未被观察到......我认为还有更多,我真的建议你看看Jon Skeet&#39 ; s C#5在复数视频上的异步课程,他实际上是通过编译器生成的代码并解释它。

答案 1 :(得分:1)

  

返回任务

Foo1.Bar只是一个常规的同步方法,它返回一些对象实例(特别是Task)。

  

或使用async ...等待

Foo2.Bar异步方法,它将被编译到状态机中。这里会有一些开销。 请注意,未来版本的Roslyn will convert方法会像这样进入同步方法。

但实际上,你不应该在这里使用Task.Run。有关详细信息,请参阅此post

答案 2 :(得分:0)

嗯,第二个实现看起来不必要复杂。如果您只需要返回任务,请创建一个任务并像第一个实现一样返回它。

第二个实现返回一个封装另一个等待任务的任务。这将产生不需要的代码膨胀,内存使用和可能的另一个线程创建,只是为了实现与第一个相同的目标。