2011-08-10 56 views
13

我想让我的手脏异步CTP和我注意到,编译器抱怨异步返回类型。其他类型的问题是什么?为什么返回类型的异步必须是无效的,任务或任务<T>

一个简单的演示

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>(); 
     });   
} 

回答

11

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

关于async方法[制作]方面,我们缺乏灵活性:我们硬编码为 ,只返回Task类型(或void)。 为什么不一致?

  1. 迭代器已经具备了这种行为...

    的迭代方法(一个具有“产量”里面)是硬编码返回要么 的IEnumerable或IEnumerator的。 但是,您可以对任何具有GetEnumerator/MoveNext/Current成员的类型进行“foreach”。 所以Async只是跟随套件。

  2. 任务就像是一个未来,所以这是很好的硬编码...

    任务是仅比未来更。 未来是语言/平台的基本基础部分。 没有理由说一种语言有两个这样的基本概念的多个副本。一个就足够了。这是非常基础的,你甚至可以添加关键字到 语言来处理期货。 无论如何,如果有一个人的未来性的东西,或任务的更丰富的内涵,那么他们可以 打造出来工作或FUNC。菜单的。 (我们的任务已经在运行。如果你想建立的东西,就是“冷”,像F# 异步操作或类似的IObservable,一个不启动,直到你告诉它 - 那么你应该 打造出来一个函数功能,而不是出任务)。

  3. 进一步微妙之处

    定义这个功能:

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

    并调用它:

    f(() => 1 + await t) 
    

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

来源:Technical intro to the Async CTP

6

因为Task<TResult>是一个“未来” - 这将在稍后到来沿着价值。 A string[]是你现在的东西。

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

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

如果您想知道为什么Task不是自动推断出来的,那么可以认为这是由Async CTP团队拒绝的。他们的理由是here,而this thread也涵盖了它。

相关问题