8

データ ソースから情報を読み取り、この情報を単純なコントローラーを備えた .NET 4.5 Web API サイトである Web サイトにプッシュする小さな .Net 4.5 C# アプリがあります。コントローラーはデータを受け取り、それをデータベースに入れます。

アプリケーションが読み取ることができるのと同じくらい速く、それを書き込むことができ、すべてが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());
        }
    }

以下は機能しません。約 1,000 件のレコードを POST し、「タスクがキャンセルされました」というメッセージとともに多数のエラーが発生しますが、約 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 レコード)、DefaultConnectionLimit が 100 の LAN 接続で部分的な成功を収めました。レイテンシー 25ms-50ms) 私は成功していません。

助けてくれてありがとう:-)

4

1 に答える 1

8

わかりました、私は今それを働いています。最大の課題は、クライアント エンドのサーバーの設定を微調整することでした。これらの設定は、テストをローカルで実行しているか、インターネットで実行しているかによって異なります。

私の「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. デフォルトの接続数: 24
  2. 最大アイドル時間: 400
  3. SemaphoreSlim 初期カウント: 50

私のLANテストでは、デフォルト接続と初期カウント値の両方を問題なく実行できました。これは予想されることです:-)

最後に、実行の最後に実行中のタスクを強制終了しないように、見た目のすぐ外に次のようにします。

     await Task.WhenAll(allTasks);

お役に立てれば!

于 2013-08-12T02:41:13.600 に答える