c# - 使用异步等待的并行多线程下载

标签 c# multithreading async-await

我有 100 多个大文件要从我的 Windows 服务 - C# 中的 Web 下载。要求是同时保持 - 最多 4 个并行 Web 文件下载。

我可以使用 async await 实现并发/并行下载,还是必须使用 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();
    }
}

关于c# - 使用异步等待的并行多线程下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50330471/

相关文章:

c# - 将小数简化为分数的算法

java - 有没有办法无意中停止 Executor 的线程?

iphone - 如何在单独的线程中执行顺序文件写入

c# - async 在这个例子中有什么好处吗?

.net - 使用 TFS 2010 运行异步任务单元测试

c# - 使用自定义成员资格和角色提供者在 MVC 中实现 IPrincipal 和 IIdentity

c# - 将带换行符的字符串输出到控制台应用程序中的文件

c# - LINQ 检查 bool 值

C# 从多个线程更新 TextBox

c# - 在 ICommand 上实现 INotifyPropertyChanged