C#5 /任务库会重写我的方法调用吗?

时间:2010-11-05 17:35:21

标签: asynchronous c#-5.0

我需要整理一些关于所有这些异步内容的东西。

假设我想加载一个大文件。根据我的理解,只需调用File.Read()并将其排队到线程池或使用Begin - / EndRead API。

据我所知,如果您使用BeginFoo / EndFoo API,您甚至不会阻止任何线程,而是只要硬件完成它的工作就会回拨给您。相比之下,从ThreadPool启动一个线程意味着你至少阻止这个特定线程用于实际上与CPU无关的工作......

到目前为止,非常好。

我想知道如果我使用File.Read,任务库实际上会做什么?它是否足够聪明,可以更改我的代码以使用BeginFoo / EndFoo API?或者只是从ThreadPool中提取一个帖子?

如果它真的改变了我的代码,我想知道它会在多大程度上追查我的代码以重写方法调用?

这有意义吗?

请帮帮我!

2 个答案:

答案 0 :(得分:3)

你说你想知道“任务库”是否会改变你的代码。有两个不同的部分 - 任务并行库(现在可以在.NET 4.0中提供),以及新的C#异步内容,它将与C#v5一起提供。

C#异步内容本身分为两部分:编译器功能和附带的库。目前还不完全清楚库中最终会出现什么 - 今天,他们在那里添加了一些扩展方法,为Task和其他一些现有的类库类型添加方法(例如,{{1}使用新的编译器功能使它们顺利运行。当C#5最终发布时,今天发布的这个C#特定库中的一些东西很可能成为.NET Framework类库的一部分。但是,它目前看起来可能会有一些可能不属于主框架类库的东西,但是其中一些可能会转移到支持DLL,就像你今天要使用的那个WebClient一样。

所以,在这样的背景下,应该很清楚任务库永远不会重写你的代码,因为它现在已经存在了,而且它只是一个库。

编译器将重写您的代码,但它主要以迭代器今天的方式执行:它将采用看起来像一个顺序方法并将其拆分为多个方法,添加一些状态跟踪以启用方法从它停止的地方起飞。

编译器不会将dynamic替换为Read。事实上,C#5对异步编程模型一无所知。 (APM是BeginRead / BeginFoo模式的正式名称。)C#5在使用EndFoo关键字时需要非常特定的模式,该关键字看起来不像任何异步今天的模式,这就是为什么异步预览带有一个为await提供扩展方法的库的原因 - 它增加了C#5所期望的方法。

(所以,为了清楚起见,当涉及到使用异步操作时,C#5对Task没有任何特殊处理。相反,异步预览不得不为Task提供一些额外的方法以使其正常工作。也就是说,C#5确实对提供商方面的Task进行了特殊处理 - 它能够生成一个代码,创建一个新的Task作为Task方法的返回值。但由于你的问题是关于消费异步功能,这在这里并不直接相关。)

具体来说,C#5将期望async关键字后面的表达式评估为可以调用await方法的内容。 (它不关心该方法是由表达式求值的对象/结构提供的,还是由扩展方法提供的。)GetAwaiter返回的内容必须提供两种方法:GetAwaiter和{ {1}}。

这是C#5将添加到代码中的唯一方法调用,因为它会将其转换为支持BeginAwait / EndAwait。此外,它不会更改代码中已有的任何方法调用 - 因此,如果您已经调用某个方法,比如async,它将不会删除它或替换它。它只会增加你已写的内容。

APM(await / Read)之间的C#5之间的关系相当长。您使用APM的方式是首先将APM工作包装在Begin(您现在已经可以在.NET 4中使用EndXxx方法的各种重载进行包装),然后您依赖于Task关键字可以使用Task.Factory.FromAsync的扩展方法。

答案 1 :(得分:1)

它只重写标记为async的方法,它只使await语句(仅适用于Task和类似的结果类型)进入异步延续。

因此,您需要运行返回任务的函数(可能称为FooTaskAsync,或者从BeginFooEndFoo对构造一个。

对普通Read的调用仍然是一个简单的同步阻塞调用。