c# - 快速高效地下载多个文件(异步)

标签 c# .net multithreading async-await

我有很多文件需要下载。所以我尝试使用如下所示的新异步功能的强大功能。

var streamTasks = urls.Select(async url => (await WebRequest.CreateHttp(url).GetResponseAsync()).GetResponseStream()).ToList();

var streams = await Task.WhenAll(streamTasks);
foreach (var stream in streams)
{
    using (var fileStream = new FileStream("blabla", FileMode.Create))
    {
        await stream.CopyToAsync(fileStream);
    }
}

我担心这段代码会导致大量内存使用,因为如果有 1000 个包含 2MB 文件的文件,那么这段代码会将 1000*2MB 流加载到内存中?

我可能遗漏了什么或者我完全正确。如果我没有错过任何东西,那么最好等待每个请求并使用流是最好的方法?

最佳答案

这两种选择都可能有问题。一次只下载一个文件不会扩展并且需要时间,而一次下载所有文件可能会造成过多的负载(另外,无需等待所有文件下载完毕再进行处理)。

我更喜欢始终使用可配置的大小来限制此类操作。一个简单的方法是使用 AsyncLock (利用 SemaphoreSlim )。更稳健的方法是使用 TPL DataflowMaxDegreeOfParallelism .

var block = new ActionBlock<string>(url =>
    {
        var stream = (await WebRequest.CreateHttp(url).GetResponseAsync()).GetResponseStream();
        using (var fileStream = new FileStream("blabla", FileMode.Create))
        {
            await stream.CopyToAsync(fileStream);
        }
    },
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 100 });

关于c# - 快速高效地下载多个文件(异步),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23891726/

相关文章:

c - 在 GTK 中使用多线程?

java - 并发log4j

c# - 类型为内部的 protected 成员的可访问性不一致

c# - Entity Framework 7 的添加迁移命令不适用于 ASP.NET 5 类库

.net - 从图像中删除下划线

c# - Rectangle.X 与 Rectangle.Left

c++ - 弹出对话框将文件保存在单独的线程中

c# - 温习 C++、C#、ASP.NET 和设计模式的知识

c# - 为什么使用平均值时图表会出现尖峰?

c# - WPF 应用程序性能