为什么返回异步类型必须为void,任务或任务<t> </t>

时间:2011-08-10 12:38:30

标签: .net async-await c#-5.0

我正在尝试用异步CTP弄脏我注意到编译器抱怨异步返回类型。其他类型有什么问题?

一个简单的演示

static void Main(string[] args)
{
    DoWork();
    Console.WriteLine("Returned to main");
    Console.Read();
}

// why do I need to return void, Task or Task<T> here?
// I know I can use something like Task<IEnumerable<string>>
private static async string[] DoWork()
{
    Console.WriteLine("DoWork started");
    return await Task.Factory.StartNew(
        delegate
        {
            Thread.Sleep(2000);                
            Console.WriteLine("DoWork done");
            return new List<string>();
        });        
}

2 个答案:

答案 0 :(得分:11)

await [消费]方面,我们很灵活:我们可以等待任何类型 有正确的方法。

async方法[生产]方面,我们不灵活:我们硬编码为 仅返回Task类型(或void)。 为什么不一致?

  1. 迭代器已经有此行为......

    迭代器方法(内部具有“yield”的方法)被硬编码以返回 IEnumerable或IEnumerator。 但是,你可以“预约”任何类型的东西 GetEnumerator / MoveNext /当前成员。 所以Async只是跟随套件。

  2. 任务就像未来一样,所以对它进行硬编码很好......

    任务只是一个未来。 未来是语言/平台的基本组成部分。 语言二没有理由有这样一个基础的多个副本 概念。一个就够了。它是如此基础,你甚至可以添加关键字 处理期货的语言。 无论如何,如果某人有类似未来的事情,或者更丰富的任务概念,那么他们就可以 用Task或Func构建它。 (我们的任务已在运行。如果你想构建一些“冷”的东西,比如F# asyncs或类似IObservable,直到你告诉它才开始 - 然后你应该 从Func而不是从任务中构建它。

  3. 进一步细微之处

    定义此功能:

    void f<T>(Func<Task<T>> f)
    

    并调用它:

    f( () => 1 + await t )
    

    在这种情况下,我们希望能够推断出T = int。除非这样推断是不可能的 编译器有硬编码知识,它传递给“f”的lambda具有类型 Task<int>

  4. 来源:Technical intro to the Async CTP

答案 1 :(得分:6)

因为Task<TResult>是一个“未来” - 一个将在以后出现的价值。你现在拥有string[]

同样,Task是将来某个时间完成(成功或出错)的操作。

void是一种特殊情况;它代表Async CTP中的顶级操作。

如果您想知道为什么不会自动推断出Task,那么Aste CTP团队会考虑这一点,但会被拒绝。他们的理由是herethis thread也涵盖了它。