代码之家  ›  专栏  ›  技术社区  ›  anelson

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

  •  5
  • anelson  · 技术社区  · 15 年前

    我有一些高性能的文件传输代码,我使用异步编程模型(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处理过这样的问题?有什么建议吗?

    1 回复  |  直到 15 年前
        1
  •  2
  •   Gabe Timothy Khouri    15 年前

    如果你担心线程太多,你可以设置 ParallelOptions.MaxDegreeOfParallelism 到您呼叫的可接受号码 Parallel.ForEach .