c# - 使用 async-await 并行多线程下载
问题描述
我的 Windows 服务 - C# 中有 100 个要从 Web 下载的多个大文件。要求是一次维护 - 最多 4 个并行 Web 文件下载。
我可以使用异步等待实现并发/并行下载还是必须使用BackgroundWorker
进程或线程?async-await 是多线程的吗?请参阅下面使用 async-await 的示例程序:
static int i = 0;
Timer_tick() {
while (i < 4) {
i++;
model = GetNextModel();
await Download(model);
}
}
private async Download(XYZ model) {
Task<FilesetResult> t = DoWork(model);
result = await t;
//Use Result
}
private async Task<FilesetResult> Work(XYZ model) {
fileresult = await api.Download(model.path)
i--;
return filesetresult;
}
解决方案
SemaphoreSlim
您可以使用类限制并行运行的异步任务的数量。就像是:
List<DownloadRequest> requests = Enumerable.Range(0, 100).Select(x => new DownloadRequest()).ToList();
using (var throttler = new SemaphoreSlim(4))
{
Task<DownloadResult>[] downloadTasks = requests.Select(request => Task.Run(async () =>
{
await throttler.WaitAsync();
try
{
return await DownloadTaskAsync(request);
}
finally
{
throttler.Release();
}
})).ToArray();
await Task.WhenAll(downloadTasks);
}
更新:感谢您的评论,已解决的问题。
Update2:动态请求列表的示例解决方案
public class DownloadManager : IDisposable
{
private readonly SemaphoreSlim _throttler = new SemaphoreSlim(4);
public async Task<DownloadResult> DownloadAsync(DownloadRequest request)
{
await _throttler.WaitAsync();
try
{
return await api.Download(request);
}
finally
{
_throttler.Release();
}
}
public void Dispose()
{
_throttler?.Dispose();
}
}
推荐阅读
- oracle - 在 PL/SQL 过程中打开动态表名的游标
- javascript - 添加剪切路径在 D3 图中隐藏了我的 y 轴
- amazon-web-services - Cloudformation:API:s3:CreateBucket 访问被拒绝
- ios - Telegram(最简单)内联机器人在 iOS 上发送照片 2 次
- node.js - 如何在没有 Bitbucket 连接的情况下在 Azure 中部署聊天机器人(NodeJS)
- python - Python模块变量不起作用
- java - 使用 eclipse 调试 OpenJDK 源代码
- ios - 我的视图在屏幕外运行并且不会向下移动
- cmake - 对“VSIInstallCurlStreamingFileHandler”的未定义引用
- ajax - 如何修复等待操作超时?工作一段时间,但不能正常工作