当异步块并发不止一个时,抛出异常会发生什么?

时间:2016-02-02 17:24:29

标签: c# .net exception-handling async-await tpl-dataflow

我有一个带有TransformBlock的DataFlow,它同时运行异步磁盘Read方法。例如,从磁盘阵列中读取多个文件,这些文件通过非单个读取请求队列深度提供性能优势。

直观地说,当最后一个ActionBlock完成时,所有管道工作都应该完成。但是,会发生以下情况:

让我们说兔子和熊开始将两个文件提取到他们自己的字节缓冲区中。 Rabbit抛出EatenByAWolf异常。 Bear稍后完成,因为它的文件有点大。当Bear从冬季长时间休眠中醒来时,EatenByAWolf异常似乎已经传播到最后一个ActionBlock的Completion等待站点。好吧,问题是我在这里清理Rabbit和Bear的字节缓冲区,导致Bear阻塞NullRefToBuffer异常。

推荐的方法是什么?我是否还应该在清除缓冲区之前等待Reader块(包含所有动物)完成,还是可以更优雅地处理它?<​​/ p>

Task.WaitAll(new[] { readerBlock.Completion, lastActionBlock.Completion });

lastActionBlock.Completion.Wait();

1 个答案:

答案 0 :(得分:1)

我在错误的抽象级别管理字节缓冲区。

我的解决方案是在创建执行多个异步读取的TransformBlock时使用有状态读取器对象。向ConcurrentBag<>读取器对象添加MyFileReaderWithCachingByteBuffers个缓冲区可确保缓冲区在封闭捕获的读取器对象超出范围之前不会进行清理。只有在所有读取操作完成后才会发生这种情况。

var fileReader = new MyFileReaderWithCachingByteBuffers(biggestFileSize);
var readerBlock = new TransformBlock<string, MyObject>(
           animal => fileReader.ReadAsync(animal),
           new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = customDOP });