如何在C#中使用TPL实现异步文件下载
How to achieve Async file download with TPL in C#
我有一个 windows 控制台客户端,它会休眠几分钟并在醒来时请求来自 Rest API 的新更新。该请求生成一个包含 json 数据的响应,其中包含一个对象列表,每个对象都包含 ID、描述、从 API 以 URL 发送到客户端的屏幕截图。控制台应用程序需要使用 json 响应,并且对于每个对象,它查找 URL 并尝试下载与列表中每个对象关联的相应图像。代码表示如下
foreach (var jobject in response)
{
Console.WriteLine(jobject.id);
Console.WriteLine(jobject.description);
if (jobject.shotUrl != null)
{
WebClient webclient = new WebClient();
webclient.DownloadFileAsync(new System.Uri(jobject.shotUrl), "F:\" + jobject.id + ".jpg");
}
}
有时可能有大约 500 个 json 个对象,这意味着 500 张照片下载...再次意味着创建 500 个网络客户端。我觉得这不是个好主意。
我的问题是:如果我依赖 TPL,我能获得性能吗?怎么做?
使用HttpClient更容易并发,你可以为class声明一个私有的HttpClient:
System.Net.Http.HttpClient _client = new System.Net.Http.HttpClient();
然后你可以编写一个方法来下载文件并将它们保存到磁盘,如下所示:
private async Task DownloadFile(string shortUrl, string destination)
{
using (var response = await _client.GetStreamAsync(shortUrl))
using (var fileStream = File.Create(destination))
{
await response.CopyToAsync(fileStream);
await fileStream.FlushAsync();
}
}
那么你可以这样使用它:
try
{
await DownloadFile(jobject.shortUrl, "F:\" + jobject.id + ".jpg");
}
catch (Exception e)
{
// Do appropriate exception handling
}
如果你想并行下载所有文件,你可以使用Task.WhenAll()
try
{
var tasks = response.Select(j => DownloadFile(j.shortUrl, "F:\" + j.id + ".jpg"));
await Task.WhenAll(tasks);
}
catch (Exception e)
{
// Do appropriate exception handling
}
我有一个 windows 控制台客户端,它会休眠几分钟并在醒来时请求来自 Rest API 的新更新。该请求生成一个包含 json 数据的响应,其中包含一个对象列表,每个对象都包含 ID、描述、从 API 以 URL 发送到客户端的屏幕截图。控制台应用程序需要使用 json 响应,并且对于每个对象,它查找 URL 并尝试下载与列表中每个对象关联的相应图像。代码表示如下
foreach (var jobject in response)
{
Console.WriteLine(jobject.id);
Console.WriteLine(jobject.description);
if (jobject.shotUrl != null)
{
WebClient webclient = new WebClient();
webclient.DownloadFileAsync(new System.Uri(jobject.shotUrl), "F:\" + jobject.id + ".jpg");
}
}
有时可能有大约 500 个 json 个对象,这意味着 500 张照片下载...再次意味着创建 500 个网络客户端。我觉得这不是个好主意。
我的问题是:如果我依赖 TPL,我能获得性能吗?怎么做?
使用HttpClient更容易并发,你可以为class声明一个私有的HttpClient:
System.Net.Http.HttpClient _client = new System.Net.Http.HttpClient();
然后你可以编写一个方法来下载文件并将它们保存到磁盘,如下所示:
private async Task DownloadFile(string shortUrl, string destination)
{
using (var response = await _client.GetStreamAsync(shortUrl))
using (var fileStream = File.Create(destination))
{
await response.CopyToAsync(fileStream);
await fileStream.FlushAsync();
}
}
那么你可以这样使用它:
try
{
await DownloadFile(jobject.shortUrl, "F:\" + jobject.id + ".jpg");
}
catch (Exception e)
{
// Do appropriate exception handling
}
如果你想并行下载所有文件,你可以使用Task.WhenAll()
try
{
var tasks = response.Select(j => DownloadFile(j.shortUrl, "F:\" + j.id + ".jpg"));
await Task.WhenAll(tasks);
}
catch (Exception e)
{
// Do appropriate exception handling
}