BeginRead
我有一些使用异步编程模型 (APM) 习惯用法(例如/ )在 C# 中编写的高性能文件传输代码EndRead
。此代码从本地磁盘读取文件并将其写入套接字。
为了在现代硬件上获得最佳性能,尽可能保持多个出色的 I/O 操作处于运行状态非常重要。因此,我BeginRead
在文件上发布了几个操作,然后当一个完成时,我BeginSend
在套接字上调用 a ,当完成时我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 上遇到过这样的问题?有什么建议么?