我有一个带有TransformBlock的DataFlow,它同时运行异步磁盘Read方法.例如,从磁盘阵列读取多个文件,这些文件通过非单个读取请求队列深度提供性能优势.
直观地说,所有管道工作应该在最后一个ActionBlock完成时完成.但是,会发生以下情况:
假设Rabbit和Bear开始将两个文件提取到它们自己的字节缓冲区中. Rabbit抛出EatenByAWolf异常. Bear稍后完成,因为它的文件有点大.当Bear从冬季长时间休眠中醒来时,EatenByAWolf异常似乎已经传播到最后一个ActionBlock的Completion等待站点.好吧,问题是我在这里清理Rabbit和Bear的字节缓冲区,导致Bear阻塞NullRefToBuffer异常.
推荐的方法是什么?我是否还应该在清除缓冲区之前等待Reader块(包含所有动物)完成,还是可以更优雅地处理?
Task.WaitAll(new[] { readerBlock.Completion, lastActionBlock.Completion });
与
lastActionBlock.Completion.Wait();
最佳答案 我在错误的抽象级别管理字节缓冲区.
对我来说,解决方案是在创建执行多个异步读取的TransformBlock时使用有状态读取器对象.添加ConcurrentBag<>缓冲区到MyFileReaderWithCachingByteBuffers读取器对象确保缓冲区不会被清除,直到闭包捕获的读取器对象超出范围.只有当所有读取操作都完成时才会发生
var fileReader = new MyFileReaderWithCachingByteBuffers(biggestFileSize);
var readerBlock = new TransformBlock<string, MyObject>(
animal => fileReader.ReadAsync(animal),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = customDOP });