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