2014-10-19 2 views
0

나는 다음과 같은 클래스가 : Task.WaitAll은 차단하고 무기한

class MultiWebProgram 
{ 
    static void Main(string[] args) 
    { 
    string[] websites = new string[] 
    { 
     "https://www.google.com/search?q=one", 
     "https://www.google.com/search?q=two", 
     "https://www.google.com/search?q=three", 
     "https://www.google.com/search?q=four" 
    }; 

    Task<int>[] taskList = new Task<int>[websites.Length]; 
    int i = 0; 
    foreach(var website in websites) 
    { 
     taskList[i] = Task<int>.Run(() => GetSiteBytes(website)); 
     i++; 
    } 
    Task.WaitAll(taskList); 
    } 

    public static int GetSiteBytes(string website) 
    { 
    WebClient client = new WebClient(); 
    var stream = client.OpenRead(new Uri(website)); 
    byte[] buffer = new byte[4096]; 
    int totalBytes = 0; 
    int bytesRead = 0; 
    do 
    { 
     bytesRead = stream.Read(buffer, 0, 4096); 
     totalBytes += bytesRead; 
    } 
    while (bytesRead >= 4096); 
    Console.WriteLine("Got {0} bytes from {1}", totalBytes, website); 
    return totalBytes; 
    } 
} 

나는이 실행

WaitAll 명령에 코드 블록.

나는이에 프로그램을 변경 시도 :

class MultiWebProgram 
{ 
    static void Main(string[] args) 
    { 
    string[] websites = new string[] 
    { 
     "https://www.google.com/search?q=one", 
     "https://www.google.com/search?q=two", 
     "https://www.google.com/search?q=three", 
     "https://www.google.com/search?q=four" 
    }; 

    Task<int>[] taskList = new Task<int>[websites.Length]; 
    int i = 0; 
    foreach(var website in websites) 
    { 
     taskList[i] = GetSiteBytesAsync(website); 
     i++; 
    } 
    Task.WaitAll(taskList); 
    } 

    public async static Task<int> GetSiteBytesAsync(string website) 
    { 
    WebClient client = new WebClient(); 
    var stream = await client.OpenReadTaskAsync(new Uri(website)); 
    byte[] buffer = new byte[4096]; 
    int totalBytes = 0; 
    int bytesRead = 0; 
    do 
    { 
     bytesRead = await stream.ReadAsync(buffer, 0, 4096); 
     totalBytes += bytesRead; 
    } 
    while (bytesRead >= 4096); 

    Console.WriteLine("Got {0} bytes from {1}", totalBytes, website); 
    return totalBytes; 
    } 
} 

을 즉, 나는 GetSiteBytes 방법 비동기했다 -하지만 차이를하지 않았다.

내가 한 일은주의해야합니다. 피들러를 시작하고 두 버전의 프로그램을 실행했을 때 차단이 없었습니다.

여기에 무슨 일이 일어날 수 있습니까?

** 편집 : ** 문제는 OpenRead 메소드 인 것 같습니다. DownloadData/DownloadDataAsync를 사용하면 차단이 사라졌습니다.

+5

하나 이상의 작업을 완료하지 못하면 Task.WaitAll()이 무기한 차단됩니다. 따라서 왜 블록 하는지를 묻는 것보다 작업 중 하나가 완료되지 않는 이유를 묻는 것이 좋습니다. 하지만 먼저 프로세스를 디버그하고 완료되지 않은 프로세스를 식별해야합니다. 결국, google.com이 동일한 클라이언트의 네 가지 동시 요청 (피들러가 일을 진행하기에 충분히 혼란 스러울 수 있음)을 인식하지 못할 수도 있습니다. 그러나 더 나은 질문이 없으면 해결책을 제시하는 것이 어려울 것입니다. –

+2

"무기한으로"말할 때 얼마나 기다렸습니까? 나를 위해, 시간은 약 2 분입니다. – svick

+2

그냥 몇 가지 추가 정보, 구글은 화면을 scrapers을 좋아하지 않아 그것을 방지하기 위해 장소에 많은 컨트롤이 있습니다. google.com으로 테스트하는 경우 많은 문제가 발생할 것입니다. 자신의 사이트에서 테스트하는 것이 가장 좋습니다. –

답변

1

모든 데이터를 읽은 후 스트림을 닫는 것을 잊었습니다. 이 시도하고 작동합니다 :

using (var stream = client.OpenRead(new Uri(website))) 
{ 
... 
} 

내가 OpenRead 방법은 후드 아래에 무엇을하는지 모르겠지만 나는 그것이 제한됩니다 일부 리소스를 할당한다고 가정하고 사용할 수있는 것보다 더 사용할 수 없습니다. 개인적으로 나는 항상 메소드가 스트림을 반환하면, 그것을 닫아야한다고 가정한다.

+0

그게 문제였습니다. 고마워, @ michał-komorowski! –