c# - 作为异步函数调用的结果返回 IEnumerable
问题描述
我有一个获取一系列项目的函数:
List<MyType> GetPage(int pageNr) {...}
要获取所有可用项目,您可以执行以下操作:
IEnumerable<MyType> FetchMyItems()
{
int pageNr = 0;
var fetchedItems = GetPage(pageNr);
while (fetchedItems.Any()
{ // there are items to return
// yield return the fetched items:
foreach (var fetchedItem in fetchedItems)
yield return fetchedItems;
// get the next page
++pageNr;
fetchedItems = GetPage(pageNr)
}
}
使用这种方法,我的用户将不再需要获取每页的项目,如果他们只需要几个项目,则只会获取第一页。当他们需要更多项目时,将自动获取更多页面。当然,缺点是我有时会多取一些不会使用的物品。
我想要一个异步版本
所以我有以下GetPage:
async Task<List<MyType>> GetPageAsync(int pageNr) {...}
根据我对 IEnumerable 的了解,它不会创建结果序列,它只会创建枚举该序列的可能性。
此枚举是使用“foreach”显式完成的,或隐式使用 LINQ 函数(如“ToList”、“ToArray”)以及“FirstOrDefault”、“Any”等函数Sum
。
var fetchItemTasks = FetchMyItemsAsync();
foreach (var fetchItemTask in fetchedItemTasks)
{
MyType fetchedItem = await fetchItemTask;
Process(fetchedItem);
}
或者,如果您执行此低级别:
var myitemsEnumerable = fetchMyItemsAsync();
// don't await yet, only create the possibility to enumerate
var enumerator = myItemsEnumerable.GetEnumerator();
while (enumerator.MoveNext())
{ // there is an item available in current:
Task<MyType> task = enumerator.Current;
return task;
}
看着这个,似乎该函数不应该返回,Task<IEnumerable<MyType>>
但是IEnumerable<Task<MyType>>
,如果你想访问一个元素,你将不得不等待这个。
因此,返回枚举等待项的可能性的函数本身并不是异步的。您无需等待可枚举,无需访问数据库等慢速提供程序即可创建此可枚举。可枚举序列中的项目是可等待的:
IEnumerable<Task<MyType>> FetchMyItems()
{
int pageNr = 0;
Task<List<MyType>> fetchItemTask = GetPageAsync(pageNr);
现在?如果我await fetchItemTask
,这些项目已经是本地的,没有什么可等待的了。如果 I fetchItemTask.Wait()
,则功能块。
解决方案
您对 async/await 模式的实现看起来不正确。
GetPageAsync
签名很好:
async Task<List<MyType>> GetPageAsync(int pageNr) {...}
现在,如果你想异步调用这个方法,你必须使用await
关键字,它会暂停正在执行的方法并将控制权返回给它的调用者,直到GetPageAsync
结果准备好:
List<MyType> items = await GetPageAsync(pageNr);
或者
Task<List<MyType>> getPageTask = GetPageAsync(pageNr);
// Some other stuff
List<MyType> items = await getPageTask;
但请注意,await
关键字只能在本身的方法内部使用async
。
可能我没有意识到您的应用程序异步模型的全部想法,但无论如何,我建议您先看看这篇关于使用 async/await 进行异步编程的 MSDN 文章。
推荐阅读
- javascript - 反应:状态的布尔标志更新不够快
- c# - 如何在 Unity 中访问子对象中的车轮对撞机
- python - 筛算法的时间复杂度
- python - pygame中的文本框
- r - 为什么在控制台中成功运行的代码在 Rmarkdown 块中返回“错误:不完整的表达式”?
- python - Django Rest Framework + psycopg2:InterfaceError:游标已关闭
- python - 如何在 python 中 sha256 原始位?
- python - RuntimeError:字典在迭代期间使用 defaultdict() 改变了大小
- java - 如何根据按下的次数改变按钮的外观?
- python - 无法通过 nipype 进行 FLIRT 注册(google colab)