【发布时间】:2025-12-01 22:15:01
【问题描述】:
在Parallel.ForEach 方法内部,当我使用异步方法DownloadWebsiteAsync 获取外部资源时,调用方法executeAsync_Click 不会等待RunDownloadParallelAsync 方法并在RunDownloadParallelAsync 完成其工作之前打印结果。
当我将DownloadWebsiteAsync 更改为DownloadWebsiteSync(以同步方式工作)时,一切正常。
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;
}
【问题讨论】:
-
我认为这里不需要并行性。您可以简单地遍历所有网站,调用
DownloadWebsiteAsync,将生成的Task<WebsiteDataModel>放在一个列表中(比如downloadTasks),然后在所有网站上调用DownloadWebsiteAsync之后(循环之后)调用await Task.WhenAll(downloadTasks),然后得到类似here 描述的结果 -
如果您的方法是
async,则不需要Parallel.ForEach,这不会增加任何内容。您现在正在做的是启动一个单独的线程,该线程启动启动任务的线程,更糟糕的是,这仍然无法正常工作,因为output.Add不是线程安全的!请考虑使用Task.WhenAll。 -
如果您希望限制可以一起运行的请求的数量,您可以执行以下操作:devblogs.microsoft.com/pfxteam/…。如果您只有少量任务,最好使用
Task.WhenAll -
Parallel.ForEach不是异步友好的。 @Servy this 是正确的重复恕我直言。 -
@TheodorZoulias 您刚刚将另一个问题与相同的解决方案联系起来。当然这是一个常见问题,因此搜索标题会导致大量重复。
标签: c# .net async-await