我有一些高性能的文件传输代码,我使用异步编程模型(APM)习惯用法(例如,
BeginRead
/
EndRead
)此代码从本地磁盘读取文件并将其写入套接字。
为了在现代硬件上获得最佳性能,在可能的情况下保持一个以上出色的I/O操作是很重要的。因此,我发布了几个
开始阅读
对文件的操作,然后当一个操作完成时,我调用
BeginSend
在插座上,完成后我再做一个
开始阅读
在文件上。细节比这要复杂一点,但在高层,这就是想法。
我已经使用了基于APM的代码,但这很难理解,而且可能有一些微妙的并发错误。我想用TPL代替它。我想
Task.Factory.FromAsync
就要这么做了,但有一个陷阱。
我看到的所有I/O样本(尤其是
StreamExtensions
类中的并行扩展插件)假定一次读取后一次写入。这不符合我的要求。
我不能用像这样简单的东西
Parallel.ForEach
或者附加条款
Task.Factory.Iterate
因为异步I/O任务不会在工作线程上花费太多时间,所以Parallel只会启动另一个任务,可能会导致数十或数百个挂起的I/O操作;太多了!你可以在那附近工作
Wait
在您的任务上,但这会导致创建事件句柄(内核对象),以及在任务等待句柄上阻塞等待,从而将工作线程绑定起来。我基于APM的实现避免了这两件事。
我一直在尝试各种不同的方法来保持多个读/写操作的正常运行,并且我已经设法使用连续性来调用一个创建另一个任务的方法,但这会让人感觉很尴尬,而且绝对不像惯用的TPL。
有没有其他人和TPL处理过这样的问题?有什么建议吗?