首页 > 解决方案 > 如何在 Parallel.ForEach 中应用异步

问题描述

Parallel.ForEach方法内部,当我使用异步方法DownloadWebsiteAsync获取外部资源时,调用方法executeAsync_Click不会等待方法并在完成工作RunDownloadParallelAsync之前打印结果。RunDownloadParallelAsync当我更改DownloadWebsiteAsyncDownloadWebsiteSync(以同步方式工作)时,一切正常。

private async void executeAsync_Click(object sender, RoutedEventArgs e)
{
    var watch = System.Diagnostics.Stopwatch.StartNew();

    var results = await DemoMethods.RunDownloadParallelAsync();
    PrintResults(results);

    watch.Stop();
    var elapsedMs = watch.ElapsedMilliseconds;

    resultsWindow.Text += $"Total execution time: { elapsedMs }";
}

public static async Task<List<WebsiteDataModel>> RunDownloadParallelAsync()
{
    List<string> websites = PrepData();
    List<WebsiteDataModel> output = new List<WebsiteDataModel>();
    
    await Task.Run(() =>
        Parallel.ForEach<string>(websites, async (site) =>
        {
            WebsiteDataModel results =await DownloadWebsiteAsync(site);
            output.Add(results);
        })
    );
    return output;
}

标签: c#.netasync-await

解决方案


Parallel并且async通常不能很好地协同工作。

在这里,您希望允许多个 HTTP 请求同时发生,但在工作中抛出多个线程将无济于事。

相反,只需使用async

public static async Task<IEnumerable<WebsiteDataModel>> RunDownloadParallelAsync()
{
    return await Task.WhenAll(PrepData().Select(DownloadWebsiteAsync));
}

每个请求都将被发送而无需等待先前的响应。


推荐阅读