如何在C#中使用TPL实现异步文件下载

时间:2016-12-25 08:43:12

标签: c# api task-parallel-library webclient

我有一个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个webclients。我觉得这不是个好主意。

我的问题是:如果我依赖TPL,我可以获得表现吗?该怎么做?

1 个答案:

答案 0 :(得分:1)

使用HttpClient对于并发更容易,您可以为该类声明一个私有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
}