簡體   English   中英

異步函數調用返回IEnumerable

[英]return IEnumerable as result of async function calls

我有一個獲取一系列項目的函數:

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'顯式完成的,或者使用諸如'ToList','ToArray'的LINQ函數隱式完成的,還可以使用'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 ,則該項目已經是本地的,不再需要等待。 如果我fetchItemTask.Wait() ,則該函數將阻塞。

您的異步/等待模式實現看起來不正確。

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的方法內使用。

可能我沒有意識到您的應用程序異步模型的全部概念,但是無論如何,我建議您先閱讀有關異步編程與異步/等待的MSDN文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM