我需要整理一些关于所有这些异步内容的东西。
假设我想加载一个大文件。根据我的理解,只需调用File.Read()
并将其排队到线程池或使用Begin
- / EndRead
API。
据我所知,如果您使用BeginFoo
/ EndFoo
API,您甚至不会阻止任何线程,而是只要硬件完成它的工作就会回拨给您。相比之下,从ThreadPool
启动一个线程意味着你至少阻止这个特定线程用于实际上与CPU无关的工作......
到目前为止,非常好。
我想知道如果我使用File.Read
,任务库实际上会做什么?它是否足够聪明,可以更改我的代码以使用BeginFoo
/ EndFoo
API?或者只是从ThreadPool
中提取一个帖子?
如果它真的改变了我的代码,我想知道它会在多大程度上追查我的代码以重写方法调用?
这有意义吗?
请帮帮我!
答案 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
,或者从BeginFoo
,EndFoo
对构造一个。
对普通Read
的调用仍然是一个简单的同步阻塞调用。