为什么返回异步类型必须为void,Task或Task <T>

ole*_*sii 13 .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>();
        });        
}
Run Code Online (Sandbox Code Playgroud)

Sko*_*ski 11

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

async方法[生产]方面,我们是不灵活的:我们硬编码只返回任务类型(或void).为什么不一致?

  1. 迭代器已经有这种行为......

    迭代器方法(内部具有"yield"的方法)被硬编码以返回IEnumerable或IEnumerator.但是,您可以"预约"任何具有GetEnumerator/MoveNext/Current成员的类型.所以Async只是跟随套件.

  2. 任务就像是未来,所以硬编码就好了......

    任务只是一个未来.未来是语言/平台的基本组成部分.语言二没有理由拥有这种基本概念的多个副本.一个就够了.它是如此基础,您甚至可以在语言中添加关键字来处理期货.无论如何,如果有人有类似未来的事情,或者更丰富的任务概念,那么他们可以用Task或Func构建它.(我们的任务已经在运行.如果你想,直到你告诉它建立东西是"冷",像F#异步操作或类似的IObservable,一个不启动 - 那么你应该建立它函数求的,而不是出来的任务).

  3. 更进一步的细微之处

    定义此功能:

    void f<T>(Func<Task<T>> f)
    
    Run Code Online (Sandbox Code Playgroud)

    并调用它:

    f( () => 1 + await t )
    
    Run Code Online (Sandbox Code Playgroud)

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

来源:Async CTP的技术介绍


Ste*_*ary 6

因为a Task<TResult>是一个"未来" - 一个将在以后出现的价值.A string[]是你现在拥有的东西.

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

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

如果您想知道为什么Task不会自动推断出来,则会考虑这一点,但Async CTP团队会拒绝这一点.他们的理由就在这里,这个主题也涵盖了它.