[英]Combine Results from Async Method and Return Synchronously
我讀過很多帖子,人們都遇到過類似的問題,但是他們似乎做出了不適用的假設,或者他們的代碼根本不適合我。 我需要結合異步方法的結果。 我想要的唯一異步的是結果的組合。 由於Azure Service Bus一次只允許我抓取256條消息,因此我想發出多個請求以一次獲取幾批並將其放入一個列表。
似乎有一個假設,如果您正在調用異步方法,則想在工作完成時返回到調用方(即:一些長時間運行的任務)。 但是,我一點都不想要。 我想等待任務完成,然后將合並的列表返回。
首先,我不想用異步標記我的調用方法。 我可以但是為什么我應該調用同步方法,而該方法恰好在返回我之前執行一些異步操作。
我已經看到了使用WhenAll()然后使用Result的示例,但這對我不起作用。 我嘗試了所有不同的排列,但是它要么鎖定了我的應用程序,要么告訴我任務尚未執行。
這是我目前擁有的:
public IEnumerable<BrokeredMessage>[] GetCombinedResults()
{
var job = () => ServiceBus.TrackerClient.ReceiveBatchAsync(BatchLimit);
Task<IEnumerable<BrokeredMessage>> task1 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
Task<IEnumerable<BrokeredMessage>> task2 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
IEnumerable<BrokeredMessage>[] results = Task.WhenAll<IEnumerable<BrokeredMessage>>(task1, task2).Result;
return results;
}
但是調用結果會導致其鎖定。 我讀過這樣做可能會發生死鎖,但已將此建議作為其他問題的答案。 如果我調用Task.WaitAll()而不關心結果,則這種類型的安裝程序可以正常工作。 不知道為什么當我想要任務返回的結果時,這變得很難。 我嘗試使用Task.Run,但是在獲得結果之前它會退出我的方法。
您似乎對使用異步進行扇出並行處理感興趣。 那是完全合法的事情。 不必使整個呼叫鏈都異步以利用扇出並行性。
您偶然發現了通常的ASP.NET死鎖。 您可以使用Task.Run
作為避免故障的一種簡單的故障安全方法。 首先,讓我們使GetCombinedResults
異步以使其簡單和一致:
public async Task<IEnumerable<BrokeredMessage>[]> GetCombinedResultsAsync()
{
var job = () => ServiceBus.TrackerClient.ReceiveBatchAsync(BatchLimit);
Task<IEnumerable<BrokeredMessage>> task1 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
Task<IEnumerable<BrokeredMessage>> task2 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
IEnumerable<BrokeredMessage>[] results = await Task.WhenAll<IEnumerable<BrokeredMessage>>(task1, task2);
return results;
}
這種方法顯然是正確的。 它不混合同步和異步。 這樣稱呼它:
var results = Task.Run(() => GetCombinedResultsAsync()).Result;
這樣做的原因是GetCombinedResultsAsync
現在無需同步上下文GetCombinedResultsAsync
執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.