2016-02-08 1 views
0

Мне интересно, есть ли способ сообщить о ходе WebClient без использования EAP (Асинхронный шаблон на основе событий). Старый способ (с использованием EAP) будет:Отчет о ходе выполнения WebClient с использованием TAP

var client = new WebClient(); 
client.DownloadProgressChanged += (s,e) => { //progress reporting } 
client.DownloadFileCompleted += (s,e) => { Console.Write("download finished" } 
client.DownloadFileAsync(file); 

с асинхронным/ОЖИДАНИЕ это можно записать в виде:

var client = new WebClient(); 
client.DownloadProgressChanged += (s,e) => { //progress reporting } 
await client.DownloadFileTaskAsync(file); 
Console.Write("downlaod finished"); 

Но во втором примере я использую как EAP и TAP (Асинхронный шаблон на основе задач). Не смешивает два шаблона асинхронности, считающихся плохой практикой?

Есть ли способ достичь этого без использования EAP? Я прочитал о Интерфейс IProgress, но я думаю, что нет возможности использовать его для отчета о прогрессе WebClient.

ответ

1

Плохая новость в том, что ответ НЕТ!

Хорошей новостью является то, что любой API EAP можно преобразовать в TAP API.

Попробуйте это:

public static class WebClientExtensios 
{ 
    public static async Task DownloadFileTaskAsync(
     this WebClient webClient, 
     Uri address, 
     string fileName, 
     IProgress<Tuple<long, int, long>> progress) 
    { 
     // Create the task to be returned 
     var tcs = new TaskCompletionSource<object>(address); 

     // Setup the callback event handler handlers 
     AsyncCompletedEventHandler completedHandler = (cs, ce) => 
     { 
      if (ce.UserState == tcs) 
      { 
       if (ce.Error != null) tcs.TrySetException(ce.Error); 
       else if (ce.Cancelled) tcs.TrySetCanceled(); 
       else tcs.TrySetResult(null); 
      } 
     }; 

     DownloadProgressChangedEventHandler progressChangedHandler = (ps, pe) => 
     { 
      if (pe.UserState == tcs) 
      { 
       progress.Report(
        Tuple.Create(
         pe.BytesReceived, 
         pe.ProgressPercentage, 
         pe.TotalBytesToReceive)); 
      } 
     }; 

     try 
     { 
      webClient.DownloadFileCompleted += completedHandler; 
      webClient.DownloadProgressChanged += progressChangedHandler; 

      webClient.DownloadFileAsync(address, fileName, tcs); 

      await tcs.Task; 
     } 
     finally 
     { 
      webClient.DownloadFileCompleted -= completedHandler; 
      webClient.DownloadProgressChanged -= progressChangedHandler; 
     } 
    } 
} 

И просто использовать его как это:

void Main() 
{ 
    var webClient = new WebClient(); 

    webClient.DownloadFileTaskAsync(
     new Uri("http://feeds.paulomorgado.net/paulomorgado/blogs/en"), 
     @"c:\temp\feed.xml", 
     new Progress<Tuple<long, int, long>>(t => 
     { 
      Console.WriteLine([email protected]" 
     Bytes received: {t.Item1,25:#,###} 
    Progress percentage: {t.Item2,25:#,###} 
Total bytes to receive: {t.Item3,25:#,###}"); 
     })).Wait(); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^