2013-08-08 15 views
7

データソースから情報を読み取り、この情報を単純なコントローラの.NET 4.5 Web APIサイトであるWebサイトにプッシュする小さな.NET 4.5 C#アプリケーションがあります。コントローラはデータを受信し、それをデータベースに格納します。.NET HTTPClient非同期の制限

私のために、次の作品、早くそれを書くことができます読み取ることができ、アプリケーションとすべてがDBで終わるよう:

public static void PostDataToWebApi(MyDataClass tData) 
    { 
     HttpResponseMessage s = null; 

     try 
     { 
      s = client.PostAsJsonAsync("/api/Station/Collector", tData).Result; 
      s.EnsureSuccessStatusCode(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("ERROR (ClientPost): " + e.ToString()); 
     } 
    } 

動作しません、次の。それは千余りのレコードに関する投稿や、すべての「タスクがキャンセルされた」というメッセージとエラーの数を思い付くが、その後、約10秒後には、処理を再開:

public static async void PostDataToWebApi(MyDataClass tData) 
    { 
     HttpResponseMessage s = null; 

     try 
     { 
      s = await client.PostAsJsonAsync("/api/Station/Collector", tData); 
      s.EnsureSuccessStatusCode(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("ERROR (ClientPost): " + e.ToString()); 
     } 
    } 

完全なエラーは以下のとおりです。

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at IICE_DataCollector_Remote.Program.<PostDataToWebApi>d__7.MoveNext() in e:\Users\TestUser.TEST\Documents\Visual Studio 2012\Projects\Test_App-trunk\TestCollector\Program.cs:line 475 

これはすばやく修正されますか?私はそれが何かを使い果たし伝えることができるものから、スレッド、:-)

任意のポインタを知っているソケットは、いただければ幸いあなたは同期POSTを行うことはかなり遅いです想像できるように、私は、この作業を取得してみたいです非同期よりも。

私のマシン、ローカルアンチウィルスまたはネットワークではないことを確かめるために、私はW2k8 R2サーバー、Windows 7仮想ゲストデスクトップ(フレッシュビルド)、Windows 8マシンで試しました。同じ結果。

詳細情報:私はこれを、小さなデータセット(10,000レコード)と100のDefaultConnectionLimitでLAN接続から部分的に成功させてテストしました。しかし、50万レコードの生産では、リモートサーバー私は何も成功していません(まだ25ms-50msの低レイテンシです)。

+0

この例外のメッセージを教えてください。 –

+0

2番目のバージョンで 'await'が欠けていませんか?それはコンパイルしてはならないようです... –

+0

@JonSkeetあなたは正しいです、私の代わりにコピー&ペーストエラー!これを修正しました。 – Dominik

答えて

8

:-)任意の助けを事前に

おかげで[OK]を、私はそれが今働いています。最も重要なのは、サーバーのクライアント側の設定を微調整することでした。これらの設定は、ローカルでテストを行っているのか、インターネットでテストしているのかによって異なります。

マイ「PostDataToWebApi」方法は、次のようになります。

public static async void PostDataToWebApi(MyDataClass tData) 
     { 

     await throttler.WaitAsync(); 
     allTasks.Add(Task.Run(async() => 
     { 

      try 
      { 
       var s = await client.PostAsJsonAsync("/api/Station/Collector", tData).ConfigureAwait(false); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("ERROR (ClientPost): " + e.ToString()); 
      } 
      finally 
      { 
       throttler.Release(); 
      } 
     })); 
    } 

私はコンソールアプリケーションの最上部に次のように宣言している:私は、次のしている私のループが始まる前に

private static List<Task> allTasks = new List<Task>(); 
    private static SemaphoreSlim throttler; 

、変数がすべて正しく動作するように変更してください:

ServicePointManager.DefaultConnectionLimit = _DefaultConnections; 
    ServicePointManager.MaxServicePointIdleTime = _MaxIdleTime; 
    ServicePointManager.Expect100Continue = false; 
    ServicePointManager.CheckCertificateRevocationList = false; 

    throttle = new SemaphoreSlim(initialCount: _MaxQueue); 

ガイドとして、私は

  1. デフォルト接続::私のために、次の作品に基づく取引をnternet 24
  2. 最大アイドル時間:400
  3. SemaphoreSlim初期カウント:私のLANのテストのために50

私は実行することができ、両方のデフォルトの接続と初期カウント値が問題なく高くなっています。これは私が推測するところです:-)

最後に、私の外見の外で、私は私がしないことを確認する実行の最後にまだ実行中のタスクをすべて終了します。

 await Task.WhenAll(allTasks); 

+0

自己回答ありがとう!これは直感的ではないようですが、セマフォの初期カウントを接続数よりも高く設定することが重要です。それ以外の場合、スループットは大幅に低下しました。 – stannius

関連する問題