2013-08-08 21 views
7

Mam małą aplikację .Net 4.5 C#, która odczytuje informacje ze źródła danych, a następnie przekazuje te informacje do witryny internetowej, która jest witryną sieci Web .NET 4.5 Web API za pomocą prostego kontrolera. Kontroler otrzymuje dane i umieszcza je w bazie danych.Ograniczenia asynchroniczne .NET HTTPClient

Poniższe działa na mnie, tak szybko, jak aplikacja może czytać to może napisać i wszystko kończy się w PB:

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()); 
     } 
    } 

Poniższa nie działa. IT posty o tysiąc-dziwnych zapisów, a następnie pojawia się z wieloma błędami wszystko z komunikatem „zadanie zostało anulowane”, ale po około 10 sekundach wznawia przetwarzanie:

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()); 
     } 
    } 

Pełne błędu:

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 

Jakieś szybkie poprawki do tego? Z tego, co mogę powiedzieć, zabrakło czegoś, nici, gniazd, kto wie :-)

Wszelkie wskazówki byłyby mile widziane, chciałbym, aby to działało, ponieważ możesz sobie wyobrazić, że robienie synchronizacji POST jest znacznie wolniejsze niż asynchronicznie.

Dla pewności nie był to mój komputer, lokalny program antywirusowy lub sieć, której próbowałem na serwerze W2k8 R2, wirtualny pulpit gościa systemu Windows 7 (nowa wersja) i komputer z systemem Windows 8, a także ten sam wynik.

Więcej informacji: Ja testowałem to z częściowym sukcesem z połączenia LAN z mniejszym zestawie danych (10000 rekordów), a DefaultConnectionLimit 100. Jednak w produkcji z 500.000 rekordów, podczas wysyłania do serwera zdalnego przez Internet (wciąż niskie opóźnienie 25ms-50ms) nie odniosłem żadnego sukcesu.

Dzięki z góry za wszelką pomoc :-)

+0

Co za wiadomość dla tego wyjątku? –

+0

Czy nie brakuje Ci "oczekującego" w swojej drugiej wersji? Wygląda na to, że nie powinno się nawet kompilować ... –

+0

@JonSkontaktuj się z nami, skopiuj i wklej błąd w moim imieniu! Poprawiłem to. – Dominik

Odpowiedz

8

Ok, mam to działa teraz. Największą sprawą było dopracowanie ustawień na końcu klienta dla serwera. Te ustawienia różniły się w zależności od tego, czy test został przeprowadzony lokalnie, czy przez Internet.

moja metoda „PostDataToWebApi” wygląda teraz tak:

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(); 
      } 
     })); 
    } 

Mam następujący zadeklarowane na szczycie mojej aplikacji konsoli:

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

Przed moich startów pętli Mam następujące, Zmieniono zmienne, aby się upewnić, że wszystko działa:

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

    throttle = new SemaphoreSlim(initialCount: _MaxQueue); 

Jako przewodnik dla I nternet transakcję w oparciu następujące prace dla mnie:

  1. domyślne połączeń: 24
  2. Max Idle Time: 400
  3. SemaphoreSlim Początkowa Count: 50

Dla mojego testu LAN mogę uruchomić zarówno domyślne połączenia i początkowe wartości zliczające są większe bez problemu, co należy się spodziewać :-)

Wreszcie, poza moim wyglądem, mam następujące rzeczy, aby upewnić się, że nie zabij wszystkie zadania, które wciąż działają po zakończeniu mojego uruchomienia:

 await Task.WhenAll(allTasks); 

Mam nadzieję, że to pomoże!

+0

Dzięki za odpowiedź automatyczną! Wygląda to na sprzeczne z intuicją, ale uznałem, że ważne jest, aby początkowy semafor był wyższy niż liczba połączeń, jak w przykładowych ustawieniach.W przeciwnym razie przepustowość została drastycznie zmniejszona. – stannius

Powiązane problemy