当异步块并发性超过一个时,引发异常时会发生什么情况

本文关键字:一个 异常 什么情况 并发 异步 | 更新日期: 2023-09-27 18:33:04

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

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

假设 Rabbit 和 Bear 开始将两个文件提取到它们自己的字节缓冲区中。 Rabbit抛出了一个EatenByAWolf异常。 熊掌记稍后完成,因为它的文件有点大。 当熊从冬季冬眠中醒来时,EatenByAWolf 异常似乎已经传播到最后一个动作块的完成等待站点。 好吧,问题是在这里我清理了兔子和熊的字节缓冲区,导致熊掌记在 NullRefToBuffer 异常上窒息。

推荐的方法是什么? 我是否也应该等待读取器块(包含所有动物(完成,然后再清除缓冲区,或者这可以更优雅地处理?

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 });