如何安全地处理使用 await foreach 检索到的 IAsyncDisposable 对象?

Posted

技术标签:

【中文标题】如何安全地处理使用 await foreach 检索到的 IAsyncDisposable 对象?【英文标题】:How to safely dispose of IAsyncDisposable objects retrieved with await foreach? 【发布时间】:2020-05-16 23:19:30 【问题描述】:

我可以使用using var 来做到这一点吗:

await foreach (var response in _container.GetItemQueryStreamIterator(query))

   using var safeResponse = response;
   //use the safeResponse

或者我应该这样做:

await foreach (var response in _container.GetItemQueryStreamIterator(query))
 
  try 
    //use response
   finally 
    response?.Dispose();
  

或者我可以不进行处理,因为迭代器是IAsyncDisposable,而await foreach 会为我处理吗?

await foreach (var response in _container.GetItemQueryStreamIterator(query))

   //use the response

【问题讨论】:

相关:What is the difference between using and await using? And how can I decide which one to use? @TheodorZoulias 谢谢你很有趣 【参考方案1】:

给定一个IEnumerable<IDisposable>(其中有或没有Async),没有关于谁应该处理元素的规则。因此,(并且希望)枚举它不会释放它的元素。

处理元素是你的责任。

在您的问题中,您要处理它们将迭代,因此选项 3 是不可能的,您必须自己处理它们。

选项 1 和 2 是等效的,但都是臭的。

你可以写:

await foreach (var item in enumerable)

  await using (item)
  
    ..          
  


// by playing with your autoformatter
await foreach (var item in enumerable) await using (item)

  ..

遗憾的是,我没有看到任何更好的解决方案。 it looks like 如果你使用 ValueType,你必须小心。 也许我们应该要求这样的东西:

await foreach(await using var e in c)

编辑当然是somebody already ask for it。

【讨论】:

感谢您使用自动格式化的建议 :)

以上是关于如何安全地处理使用 await foreach 检索到的 IAsyncDisposable 对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何优雅地处理Async/Await的异常?

Js不使用try catch,优雅地处理await报错的情况

forEach中使用async await的问题

优雅地处理 `await`ed Javascript Promise 上的拒绝

JS Async / Await与forEach不兼容

Parallel.ForEach 和 async-await [重复]