[英]Why does this ParallelForEachAsync-Method never return?
我嘗試使用該項目中的 ParallelForEachAsync 方法異步和並行執行此代碼: https : //github.com/Dasync/AsyncEnumerable 。 不幸的是,該方法永遠不會返回。 SampleProduct 是一個簡單的 DTO,它具有一個布爾屬性和兩個字符串屬性。 GetOsmData 方法嘗試通過 http 請求獲取數據但經常拋出異常。
我的第一次嘗試沒有使用 .ConfigureAwait(false),但結果相同......如果我用產品列表 (products.Count = 8) result.Count 嘗試這種方法,結果總是以 7 停止。
private async Task<ConcurrentBag<SampleProduct>> CheckOsmDataAsync(List<SampleProduct> products)
{
var result = new ConcurrentBag<SampleProduct>();
await products.ParallelForEachAsync(
async product =>
{
OsmData osmData;
try
{
osmData = await GetOsmData(_osmUrl.Replace("articlenumber", product.MaterialNumber.ToString())).ConfigureAwait(false);
}
catch (Exception e)
{
osmData = null;
}
if (osmData != null && osmData.PrintingData.Count > 0)
{
product.OsmPrintImageAvailable = true;
}
else
{
product.OsmPrintImageAvailable = false;
}
result.Add(product);
},
// 0 => Chooses a default value based on the processor count
maxDegreeOfParallelism: 0
);
return result;
}
在某些情況下, GetOsmData
方法是否可能永遠不會返回? 為了排除這種可能性,您可以在合理的持續時間后強制其超時。 您可以使用下面的擴展方法來實現它:
public static Task<T> TimeoutAfter<T>(this Task<T> task, int timeout)
{
var delayTask = Task.Delay(timeout).ContinueWith<T>(_ => throw new TimeoutException(),
TaskContinuationOptions.ExecuteSynchronously);
return Task.WhenAny(task, delayTask).Unwrap();
}
可以這樣使用:
osmData = await GetOsmData(_osmUrl.Replace("articlenumber",
product.MaterialNumber.ToString())).TimeoutAfter(5000).ConfigureAwait(false);
這不是永久性的修復,因為我們不知道GetOsmData
任務下一步將做什么,因為它現在已經變成流氓 。 糟糕的情況是,它將使線程池線程永遠被占用,並且由於過多的流氓任務,線程池遲早會耗盡。 希望這不是您要處理的問題,因為如果是這樣,這並不是一個容易解決的問題。
在同事的幫助下,我可以解決問題...問題不在於方法本身內部,而僅在於調用方法的方式。 我稱它為主/ UI線程同步。 這似乎造成了僵局。 使調用方法異步並等待CheckOsmDataAsync()解決了該問題。
不過,感謝您的回復!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.