2012-04-02 3 views
0

WebClient를 사용하여 서버에서 일부 JSON 데이터를 가져옵니다. 그리고 나는 그것이 동기 (예, 나는 WP에서 모든 것이 비동기이어야한다는 것을 알고 싶지만, 어떤 이유로 동기화가 필요하다.). 제 수업에서는 다음과 같은 코드를 가지고 있습니다 :WebClient - 큰 데이터로 응답 동기화

private WebClient _webClient; 
    private string _acctualResponse; 
    private AutoResetEvent _lock = new AutoResetEvent(false); 

    void _webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e) 
    { 
     _acctualResponse = e.Result; 
     _lock.Set(); 
    } 

    public string _message; 
    public string SendString(string URL, string message) 
    { 
     _webClient.UploadStringAsync(new Uri(URL), message); 
     _lock.WaitOne(); 
     return _acctualResponse;  
    } 

제 프로그램에서는 몇 가지 다른 데이터 세트를 얻으 려합니다. 반환 데이터는 작지만 모든 것이 정상적으로 작동합니다. 내가 더 큰 데이터 (base64에서 3 img)를 가져야 할 때, 이벤트는 시작되지 않습니다. 하지만! _lock을 제거했을 때, 이벤트는 항상 SendString 기능이 끝난 후 잠깐 시작됩니다. 응답을 기다리는 다른 메커니즘을 사용하려고합니다. while 루프 :

private void WaitForResponse() 
    { 
     _acctualRequestTime = 0; 
     _acctualResponse = null; 
     while (!_uploadComplet && _acctualRequestTime < Timeout) 
     { 
      int slepTime = 200; 
      Thread.Sleep(slepTime); 
      _acctualRequestTime += slepTime; 
     } 
     _uploadComplet = false; 
    } 

efect에도이 동일 [물론, 경우에 내가 참으로 _uploadComplete 플래그를 설정되었다] : 응답은 상관없이 어떤 설정된 제한 시간 간격, 타임 아웃 후 짧은왔다 없습니다. 나는이 상황에 약간 혼란 스럽다. 내가 뭘 잘못하고 있는지 알아?

+0

예상되는 비동기 디자인 철학에 맞서고 있지만 왜 그런지 말하지는 않습니다. 어쩌면 당신은 그 이유를 쓸 수 있고, 우리는 당신에게 당신의 문제를 해결하는 대답을 줄 수 있지만, 당신이이 농구를 뛰어 넘을 필요는없는 것입니까? –

답변

1

이 문제도 발생했습니다.

public T Get<T>(string apiMethod) where T : class 
     { 
      T outputObject; 
      lock (syncObj) 
      { 
       downloadHandle = new ManualResetEvent(false); 

       ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadAsync), apiMethod); 
       downloadHandle.WaitOne(); 
       outputObject = JsonHelper.Parse<T>(result); 
      } 
      return outputObject; 
     } 

protected 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 (Exception ex) 
      { 
       downloadHandle.Set(); 
      } 
     } 

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
     { 
      (sender as WebClient).DownloadStringCompleted -= client_DownloadStringCompleted; 

      try 
      { 
       result = e.Result; 
      } 
      catch (Exception ex) 
      { 
       result = ex.Message; 
      } 
      finally 
      { 
       downloadHandle.Set(); 
      } 
     } 

는 이제 다음과 같이 사용할 수 있습니다 :

public Song GetSong(int _id) 
     { 
      var wr = Get<SongInfoWrapper>("info/song/" + _id); 
      if (wr != null) 
      { 
       if (wr.Error == null) 
       { 
        return wr.Element; 
       } 
      } 

      return null; 
     } 

을하지만 GetSong 방법은 UI 스레드가 아닌라는 것을 확신 할

이 사용할 수 있습니다.

0

WebClient은 요청이 UI 스레드에서 시작된 경우 UI 스레드에서 이벤트를 발생시킵니다. 따라서 UI 스레드에서 대기 중이며 기본 이벤트 루프를 제어하지 않으면 이벤트가 대기열에 배치되어 전달되지 않습니다.

WebClient은 UI 스레드에서 모든 처리를 수행하므로 Microsoft 및 다른 많은 사람들은 UI 스레드를 사용하지 않는 것이 좋습니다. 대신 WebRequest을 사용해야합니다. 그것은 당신의 문제를 해결할 수도 있습니다. (비록 UI 스레드를 차단하는 것이 좋은 일은 아닙니다.)

+0

나는 'WebRequest'도 시도했다. 효과는 같았습니다 : ( – Thaven

+0

백그라운드 스레드에서 WebRequest를 시작해야하며, 그렇지 않으면 블로킹 UI 스레드로 이벤트를 전달할 수 없습니다. – Codo