为什么异步的返回类型必须为void,任务或任务&LT; T&GT; [英] Why return type of async must be void, Task or Task<T>
问题描述
我试图让我的手脏与异步CTP和我注意到,编译器抱怨异步返回类型。什么是与其他类型的问题?
一个简单的演示
静态无效的主要(字串[] args)
{
做工作();
Console.WriteLine(返回到主);
Console.Read();
}
//为什么我需要返回void,任务或任务&LT; T&GT;这里?
//我知道我可以使用类似任务&LT; IEnumerable的&LT;字符串&GT;&GT;
私有静态异步的String []的DoWork()
{
Console.WriteLine(DoWork的开始);
返回等待Task.Factory.StartNew(
代表
{
Thread.sleep代码(2000);
Console.WriteLine(DoWork的完成);
返回新的List&LT;字符串&GT;();
});
}
在等待
[消费]方面,我们是灵活的:我们可以等待任何类型的,只要它
有正确的方法。
在异步
法[制作]一面,我们是不灵活的:我们是硬coded到
仅返回任务类型(或无效)。
为什么不一致?
-
迭代器已经具备了这种行为...
这是迭代法(其中一个具有收益内)是硬codeD回任 的IEnumerable或IEnumerator的。 但是,您可以的foreach在任何类型的有 的GetEnumerator / MoveNext的/当前的成员。 因此,异步只是下面的套件。
-
任务就像是一个未来的,所以这是很好的硬code吧...
一个任务是仅比未来更。 将来是一个语言/平台的一个基本的基本组成部分。 没有理由为一个语言两人这样一个基本的多个副本 概念。一个就够了。它是如此的基础,你甚至可以添加关键字到 语言处理期货。 无论如何,如果有人有未来性的东西,或任务更丰富的概念,那么他们可以 打造出来的任务或函数功能的。 (我们的任务已经在运行。如果你想建立的东西,就是冷,如F# asyncs或类似的IObservable,一种不启动,直到你告诉它 - 那么你应该 打造出来一个函数功能,而不是一项任务的)。
-
此外微妙
定义这个功能:
无效F&LT; T&GT;(Func键&LT;任务&LT; T&GT;&GT; F)
和调用它:
F(()=&GT; 1 +等待T)
我们希望能够推断出T = INT在这种情况下。这种推断是不可能的,除非 编译器硬codeD知识拉姆达它传递到F的类型为
任务&LT; INT&GT;
来源:<一href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-12-06/4466.Technical-intro-to-the-Async-CTP.pdf"相对=nofollow> 技术介绍到异步CTP 的
I am trying get my hands dirty with async CTP and I noticed that the compiler complains about the async return type. What is the problem with other types?
A simple demo
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>();
});
}
On the await
[consumption] side, we are flexible: we can await any type so long as it
has the right methods.
On the async
method [production] side, we are inflexible: we are hard-coded to
return only the Task type (or void).
Why the inconsistency?
Iterators already have this behavior...
An iterator method (one which has a "yield" inside) is hard-coded to return either IEnumerable or IEnumerator. However, you can "foreach" over any type which has GetEnumerator/MoveNext/Current members. So Async is just following suite.
A task is like a future, so it’s good to hard-code it...
A Task is barely more than a future. A future is a basic fundamental part of a language/platform. There’s no reason for a language two have multiple copies of such a fundamental notion. One is enough. It’s so foundational that you might even add keywords to the language to deal with futures. Anyway, if someone has a future-like thing, or a richer notion of task, then they can build it out of Task or Func. (Our Tasks are already running. If you want to build something that’s "cold", like F# asyncs or like IObservable, one which doesn’t start until you tell it – then you should build it out of a Func rather than out of a Task).
Further subtleties
Define this function:
void f<T>(Func<Task<T>> f)
And invoke it:
f( () => 1 + await t )
We’d like to be able to infer that T=int in this case. Such inference isn’t possible unless the compiler has hard-coded knowledge that the lambda it passes to "f" has type
Task<int>
.
Source: Technical intro to the Async CTP
这篇关于为什么异步的返回类型必须为void,任务或任务&LT; T&GT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!