【发布时间】:2021-04-15 23:48:35
【问题描述】:
假设我想从网站下载 1000 个食谱。这些网站最多接受 10 个并发连接。 每个配方都应该存储在一个数组中,在其对应的索引处。(我不想将数组发送到DownloadRecipe 方法。)
从技术上讲,我已经解决了这个问题,但我想知道是否有更简洁的方法来使用 async/await 或其他方法来实现它?
static async Task MainAsync()
{
int recipeCount = 1000;
int connectionCount = 10;
string[] recipes = new string[recipeCount];
Task<string>[] tasks = new Task<string>[connectionCount];
int r = 0;
while (r < recipeCount)
{
for (int t = 0; t < tasks.Length; t++)
{
tasks[t] = Task.Run(async () => recipes[r] = await DownloadRecipe(r));
r++;
}
await Task.WhenAll(tasks);
}
}
static async Task<string> DownloadRecipe(int index)
{
// ... await calls to download recipe
}
此外,此解决方案不是最佳解决方案,因为在所有 10 次运行下载完成之前,它不会开始新的下载。有什么我们可以在那里改进而不会使代码过于臃肿的地方吗?线程池限制为 10 个线程?
【问题讨论】:
-
我不确定它是否会对您有所帮助,但是从 C# 8.0 开始,您可以使用异步迭代和异步 foreach 循环来处理 docs.microsoft.com/en-us/archive/msdn-magazine/2019/november/… 也许它会帮助您更轻松地实现您想要的东西跨度>
-
我认为您的解决方案之所以有效,是因为
recipeCount可以被connectionCount整除。否则会在此处发生参数超出范围异常:recipes[r] = await...。您的解决方案可能也容易受到此问题的影响:Captured variable in a loop in C#,关于变量r。 -
@TheodorZoulias 是的,你是对的。我稍微重写了解决方案以使其更短并清楚地显示我想要改进的代码。对我来说幸运的是,这些问题都不存在于我的较长解决方案中。谢谢指出!
标签: c# asynchronous async-await threadpool