使用任务并行库执行异步I/O的建议

ane*_*son 5 asynchronous .net-4.0 task-parallel-library

我有一些高性能的文件传输代码,我在C#中使用异步编程模型(APM)习语(例如BeginRead/ EndRead)编写.此代码从本地磁盘读取文件并将其写入套接字.

为了在现代硬件上获得最佳性能,尽可能在飞行中保留多个出色的I/O操作非常重要.因此,我BeginRead在文件上发布了几个操作,然后当一个完成时,我BeginSend在套接字上调用一个,当完成时我BeginRead在文件上做另一个操作.细节有点复杂,但在高层次上就是这个想法.

我有基于APM的代码工作,但它很难遵循,可能有微妙的并发错误.我很乐意为此使用TPL.我认为Task.Factory.FromAsync只是这样做,但有一个问题.

我见过的所有I/O示例(特别StreamExtensions是Parallel Extensions Extras中的类)假定一次读取后跟一次写入.这不会按我需要的方式执行.

我不能使用简单的东西Parallel.ForEach或Extras扩展,Task.Factory.Iterate因为异步I/O任务不会在工作线程上花费太多时间,因此Parallel只启动另一个任务,导致可能有数十或数百个挂起的I/O操作; 方式太多了!您可以通过Wait执行任务来解决这个问题,但这会导致创建事件句柄(内核对象),以及阻塞等待工作线程的任务等待句柄等待.我的基于APM的实现避免了这两件事.

我一直在玩不同的方法来保持飞行中的多个读/写操作,我已经设法使用延续调用一个创建另一个任务的方法,但它感觉很尴尬,并且肯定不喜欢惯用的TPL.

还有其他人在使用TPL时遇到过这样的问题吗?有什么建议?

Gab*_*abe 2

如果您担心线程过多,您可以ParallelOptions.MaxDegreeOfParallelism在调用中设置为可接受的数字Parallel.ForEach