2016-12-13 2 views
1

DownloadFileAsyncTask 파일을 다운로드하는 방법을 사용하고 있습니다. 그러나 루프에서 실행할 때 예외가 발생합니다. 이는 동시 작업이 지원되지 않는다고 알려줍니다. 반복의 수 (1-5) 큰없는 경우이전 다운로드가 완료 될 때까지 WebClient를 대기시키는 방법?

public async Task<string> Download(string uri, string path) 
    { 
     if (uri == null) return; 

     //manually wait for previous task to complete 
     while (Client.IsBusy) 
     { 
      await Task.Delay(10); 
     } 

     await Client.DownloadFileTaskAsync(new Uri(absoluteUri), path); 

     return path; 
    } 

때로는 작품, 그리고 10 번 이상 실행하면이 오류를 받고 있어요 :이처럼 그것을 해결하기 위해 노력했다. Client 여기에 WebClient이며 한 번 만듭니다. 나는 그것이 오버 헤드를 만들기 때문에 모든 반복마다 새로운 클라이언트를 생성하지 않습니다. 내가 이전에 다운로드가 완료되기 전에 WebClient을 기다리는 방법을 말하고 있었습니까? 또한 여기에 질문은 작은 다운로드를 위해 IsBusy이 작동하는 이유입니다. 내가 사용하고 코드 :

public IEnumerable<Task<string>> GetPathById(IEnumerable<Photo> photos) 
    { 
     return photos?.Select(
        async photo => 
        { 
         var path = await Download(Uri, Path); 
         return path; 
        }); 
    } 

나는 많은 파일을 다운로드하려면 내 UI 스레드를 차단하지 않습니다. 어쩌면 다른 방법이 있을까요?

+3

당신이 오직 그들이 실제로 자신의 일을하기 전에 각각의 어떤 다른 작업을하지 않습니다 때까지 기다려야 할 거라면 왜 처음에 동시에 다운로드를 많이 수행하는? 한 번에 하나씩 만 다운로드하려면 한 번에 두 개 이상 시작하지 마십시오. 이전 하나가 끝나면 다음 별에만 별표를 표시하십시오. – Servy

+1

. 나는 그것이 오버 헤드를 만들기 때문에 모든 반복마다 새로운 클라이언트를 생성하지 않습니다. 정말로 오버 헤드입니까? – MistyK

+0

@Zbigniew 다양한 다운로드를 병렬로 실행하는 것과 순차적으로 실행하는 것의 차이점은 다음과 같습니다. 그러면 네트워크로드 밀도가 크게 높아집니다. 실제로 병렬 작업을 수행 할 것인지 (또는 수행 할 수 있는지) 여부는 상황에 따라 다릅니다. – Servy

답변

2

도움이되는 데 필요한 많은 코드가 누락되어 있으므로이 간단한 예제를 통해 내가 생각한 것을 보여 줄 수 있습니다. 그것의 .NET 핵심하지만 본질적으로 동일, 단지 WebClient에 대한 HttpClient를 교환.

static void Main(string[] args) 
{ 
    Task.Run(async() => 
    { 
     var toDownload = new string[] { "http://google.com", "http://microsoft.com", "http://apple.com" }; 
     var client = new HttpClient(); 

     var downloadedItems = await DownloadItems(client, toDownload); 

     Console.WriteLine("This is async"); 

     foreach (var item in downloadedItems) 
     { 
      Console.WriteLine(item); 
     } 

     Console.ReadLine(); 
    }).Wait(); 
} 

static async Task<IEnumerable<string>> DownloadItems(HttpClient client, string[] uris) 
{ 
    // This sets up each page to be downloaded using the same HttpClient. 
    var items = new List<string>(); 
    foreach (var uri in uris) 
    { 
     var item = await Download(client, uri); 
     items.Add(item); 
    } 
    return items; 
} 

static async Task<string> Download(HttpClient client, string uri) 
{ 
    // This download the page and returns the content. 
    if (string.IsNullOrEmpty(uri)) return null; 

    var content = await client.GetStringAsync(uri); 
    return content; 
} 
+1

매우 드물게'ContinueWith'를 사용해야합니다. 거의 항상 당신이하고있는 일을 당신이 알고있는 매우 드문 경우 외에는 '기다리는 것'을 사용해야합니다. – Servy

+0

@Servy ContinueWith를 제거하기 위해 코드를 업데이트했습니다. – Stephen