2012-04-02 12 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; 
    } 

が[もちろん、イベントで私がtrueに_uploadCompleteフラグを設定しました] EFECTが同じであった:応答は関係なく、間隔が設定されたものタイムアウト、タイムアウト後に短いが来ませんでした。 私はこの状況で少し混乱しています。私は悪いことを知っていますか?

+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や他の多くのユーザーはこれを使用することをお勧めします。代わりにWebRequestを使用する必要があります。あなたの問題を解決することすらできます。 (UIスレッドをブロックすることはまさに良いことではありませんが)。

+0

私は 'WebRequest'も試みました。効果は同じでした:( – Thaven

+0

バックグラウンドスレッドでWebRequestを開始する必要があるかもしれません。そうしないと、ブロッキングUIスレッドにイベントを配信できません。 – Codo

関連する問題