簡體   English   中英

為什么這個 ParallelForEachAsync-Method 永遠不會返回?

[英]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.

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