3

내가 코드를ManualResetEvent.WaitOne 블록 모든 스레드

ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadAsync), apiMethod); 
downloadHandle.WaitOne(); 

을 다음했다. 하지만 왜 그런지 모르겠다. DownloadAsync 및 downloadHandle.WaitOne()에 대한 새 스레드를 만들어 그를 차단해서는 안됩니다.

내가 필요한 것은 비동기가 아닌 동기화 방법을 만드는 것입니다.

감사합니다.

UPD : 비동기 호출로 업데이트 된 소스 코드.

+0

어떤 스레드에서 'downloadHandle.WaitOne' 코드가 호출 되었습니까? UI 스레드? –

답변

4

client.DownloadString은 동기 메서드이므로 완성 된 처리기가 호출되지 않습니다. 비동기 버전을 호출해야합니다 : client.DownloadStringAsync()

DownloadStringAsync에 대한 자세한 내용은 msdn에서 읽을 수 있습니다. 또한 try-catch 블록에 코드를 넣고 예외를 처리하는 것이 현명한 경우에는 일부 코드를 호출해야합니다.

코드는 다음과 같을 수 있습니다 :

private void DownloadAsync(object _uri) 
{ 
    try 
    { 
     var url = _uri as string; 
     WebClient client = new WebClient(); 
     client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); 
     client.DownloadStringAsync(new Uri(GLOBALS.MAIN_API_URL + url, UriKind.Absolute)); 
    } 
    catch //appropriate exception 
    { 
     //Handle exception (maybe set downloadHandle or report an error) 
    } 
} 

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
{ 
    result = e.Result; 
    downloadHandle.Set(); 
} 
+0

... 물론 이것이 있습니다 :-) - 또한 DownloadAsync를 호출하기 위해 여기에 스레드 풀을 사용할 필요가 없습니다. –

+0

@SashaGoldshtein 물론 당신이 옳다. 나는 이것을 이전에 발견하지 못했다. +1 –

+0

어쨌든 작동하지 않습니다. =) downloadHandle이 설정되지 않은 동안에는 client_DownloadStringCompleted가 호출되지 않습니다. –

2

호출되는 완료 콜백 메소드를 방지하는 예외가있을 수 있습니다. 그것이 전혀 호출되었는지 확인 했습니까?

그런데 여기 실제로 스레드 풀을 사용할 필요는 없습니다. 차단하지 않기 때문에 주 스레드에서 DownloadAsync()를 호출 할 수 있습니다.

0

downloadHandle.WaitOne();UI으로 호출하면 UI thread을 차단하므로 ThreadPool은 절대 호출되지 않습니다. 배경으로 이동 :

ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadAsync), apiMethod); 
downloadHandle.WaitOne(); 
+0

배경으로 이동한다는 것은 무엇을 의미합니까? 이 코드는 ViewModel에서 처리되므로 UI ​​스레드가 차단되지 않습니다. –

+0

'UI'에서'ViewModel' 메소드를 호출하면'UI'에서 실행됩니다. 하지만 전화의 상황을 알 수는 없으므로 어디에서 문제인지 추측 할 수 있습니다. – Ku6opr

2

내 생각에 : 당신은 UI 스레드에서 downloadHandle.WaitOne()으로 전화를 걸고 있습니다. UI 이벤트 핸들러에서 코드를 실행하는 경우 (예 : 클릭, 버튼 또는 탐색 페이지 탐색) 또는 이벤트 핸들러에서 호출하는 함수는 UI 스레드에 있습니다.

왜 이것이 문제입니까?

물론, 스레드 풀 덕분에 백그라운드에서 DownloadAsync이 실행됩니다. 그러나 WebClient 클래스는 항상 UI 스레드를 사용하여 콜백 (즉, client_DownloadStringCompleted 메서드)을 실행하지만 ...이 매우 동일한 스레드는 downloadHandle.WaitOne()에 의해 차단됩니다!

자물쇠에 타임 아웃을 걸면 client_DownloadStringCompleted 메쏘드가 마술처럼 실행됩니다.

해결 방법? 두 가지 솔루션.

1/메인 스레드에서 downloadHandle.WaitOne() 실행을 중지합니다. 그것은 사용자 인터페이스를 차단하고 응용 프로그램이 응답하지 않게됩니다. 결코은 좋은 것입니다.

2/WebClient 대신 HttpWebRequest을 사용하십시오.HttpWebRequest은 다운로드를 시작한 동일한 스레드에서 콜백을 실행하므로이 교착 상태 문제가 발생하지 않습니다.

관련 문제