2011-09-16 17 views
3

要件複数の非同期Webクライアントコール(シルバー4)

  • ユーザーのコンピュータからファイルをロードしますSilverlightのクライアント。
  • ファイルの各行について、URLにGETを発行し、返されたJSON検証メッセージに基づいて行を承認または拒否する必要があります。
  • すべての行が完了したら、渡された行の数と失敗した行の数をユーザーに表示します。

私はBackgroundWorkerでこれを "同期的に"実行することをお勧めしましたが、それはSL非同期の考え方を破ります。

私のコードは現在OpenFileDialogの結果をファイルを強く型付けされたオブジェクトのリストに読み込むBackgroundWorkerに渡します(クライアント側の検証)。私はWebClientを作成し、回線をループするときに何度もDownloadStringAsyncを呼び出します。多くの場合、バックグラウンドワーカーはWebClientが完了する前に完了したイベントメソッドを完了して実行します。 UIスレッドは、必要に応じて非同期で実行できますが、実際にデータを取得するまでbackgroundworkerスレッドを完了するか、すべての(数百)行が検証されたときに動作する追加のイベントハンドラが必要です。

Xの合計イベントの最後のCompletedイベントを処理したい場合のベストプラクティスは何ですか?ここで自動リセットイベントを使用すると役立ちますか?

+0

ファイル全体をサーバーに送信してから、サーバーへの1回のラウンドトリップで検証メッセージの完全なセットを取得するだけではない理由はありますか? – AnthonyWJones

+0

@AnthonyWJonesファイルサイズ、行数、およびユーザーへの報告の進捗状況によって、このアプローチが選択されました。 「完全ダンプ」を最初にテストしましたが、処理に時間がかかり、ユーザーにライブレポートを返すことは、技術的には機能しない場合は、より機能的なアプローチとみなされました。 – Henrik

答えて

1

この場合、バックグラウンドスレッドに移動する必要はありません。AutoResetEventを使用する必要はありません。ファイルを読み終わったら、行数(=送信するリクエスト数)を数え、それをインスタンス変数に格納します。 WebRequest.DownloadAsync(またはデータをダウンロードする別のWebClient非同期呼び出し)を起動します。 asyncメソッドの各コールバックでは、Interlock.Decrementにインスタンス変数があり、0になるとすべての結果が得られ、クライアントに要約を表示できることがわかります。

+0

ファイルの処理と未処理のWebリクエストの100秒の設定が、UIスレッドでやりたいことであるかどうかはわかりません。実際、WebClientの各インスタンスが100件あり、完了した時点でUIスレッドにイベントが発行されるという未解決のリクエストがあるとは思えません。 – AnthonyWJones

1

ランダム応答シーケンス(しかし、並列実行) または順序付き応答を選択できますが、順次モードです。 さまざまな反対意見があります。

using System; 
using System.Net; 
using System.Reactive.Linq;//Rx libriary 
using System.Threading; 
using System.Windows; 
using System.Windows.Controls; 

public partial class MainPage : UserControl 
{ 
    private int count = 0; 
    private int error = 0; 

    public MainPage() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     ThreadPool.QueueUserWorkItem(StartParallel); 
     //ThreadPool.QueueUserWorkItem(StartSequential); 
    } 

    private void Update(Exception exception) 
    { 
     if (exception == null) 
      Interlocked.Increment(ref count); 
     else 
      Interlocked.Increment(ref error); 
     if ((count%100) == 0) 
     { 
      int count1 = count; 
      Dispatcher.BeginInvoke(() => { textBox.Text = count1.ToString(); }); 
     } 
    } 

    private void StartSequential(object o) 
    { 
     //single instance of WebClient 
     WebClient wc = new WebClient(); 
     var observer = Observable.FromEventPattern<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted") 
      .Select(newResult => new {newResult.EventArgs.Error, newResult.EventArgs.Result}); 

     wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx")); 
     int i = 0; 
     foreach (var nextValue in observer.Next()) 
     { 
      if (i == 10000) break; 
      wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx")); 
      Update(nextValue.Error); 
     } 
    } 

    private void StartParallel(object o) 
    { 
     for (int i = 0; i < 10000; i++) 
     { 
      //multiple instance of WebClient 
      WebClient t = new WebClient(); 
      t.DownloadStringCompleted += 
       (x, nextValue) => Update(nextValue.Error);//order of result sequence is not guaranteed 
      t.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx")); 
     } 
    } 
} 
関連する問題