我正在尝试用异步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>();
});
}
答案 0 :(得分:11)
在await
[消费]方面,我们很灵活:我们可以等待任何类型
有正确的方法。
在async
方法[生产]方面,我们不灵活:我们硬编码为
仅返回Task类型(或void)。
为什么不一致?
迭代器已经有此行为......
迭代器方法(内部具有“yield”的方法)被硬编码以返回 IEnumerable或IEnumerator。 但是,你可以“预约”任何类型的东西 GetEnumerator / MoveNext /当前成员。 所以Async只是跟随套件。
任务就像未来一样,所以对它进行硬编码很好......
任务只是一个未来。 未来是语言/平台的基本组成部分。 语言二没有理由有这样一个基础的多个副本 概念。一个就够了。它是如此基础,你甚至可以添加关键字 处理期货的语言。 无论如何,如果某人有类似未来的事情,或者更丰富的任务概念,那么他们就可以 用Task或Func构建它。 (我们的任务已在运行。如果你想构建一些“冷”的东西,比如F# asyncs或类似IObservable,直到你告诉它才开始 - 然后你应该 从Func而不是从任务中构建它。
进一步细微之处
定义此功能:
void f<T>(Func<Task<T>> f)
并调用它:
f( () => 1 + await t )
在这种情况下,我们希望能够推断出T = int。除非这样推断是不可能的
编译器有硬编码知识,它传递给“f”的lambda具有类型
Task<int>
。
答案 1 :(得分:6)
因为Task<TResult>
是一个“未来” - 一个将在以后出现的价值。你现在拥有string[]
。
同样,Task
是将来某个时间完成(成功或出错)的操作。
void
是一种特殊情况;它代表Async CTP中的顶级操作。
如果您想知道为什么不会自动推断出Task
,那么Aste CTP团队会考虑这一点,但会被拒绝。他们的理由是here,this thread也涵盖了它。