繁体   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