2010-11-12 13 views
6

Potrzebuję wykonać wiele asynchronicznych wywołań z wnętrza usługi wcf hostowanej w IIS (może być istotne, nie wiem). Połączenia są do innych usług, ale robię je przez napisanie napisu na adres URL usługi. Dzielenie się nimi synchronicznie działa, ale mam więcej niż tuzin połączeń i są one całkowicie niezależne, więc chciałbym je przyspieszyć, nazywając je asynchronicznie.Oczekiwanie na wiele asynchronicznych żądań POST

Teraz zdaję sobie sprawę, że mogę po prostu użyć wielu wątków - i to może być najłatwiejsze rozwiązanie - ale pomyślałem, że spróbuję.

Mój kod jest podobny do tego:

public delegate void Callback(string response); 

public static void InvokeAsync(string request, string url, Callback callback) 
    where TResponse: class 
{ 
    var web = new WebClient(); 
    web.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); 

    web.UploadStringCompleted += (sender, e) => callback.Invoke(e.Result); 
    web.UploadStringAsync(new Uri(url), request); 
} 

//... 
var lockObj = new object(); 
foreach (var item in list) 
    InvokeAsync(item, url, response => { lock(lockObj) newList.Add(response); }); 

Powyższe powinno działać, wierzę; jednak moim problemem jest to, że nie mam pojęcia, jak poczekać, aż wszystkie odpowiedzi wróci. Jeśli używam licznika i czekam w pętli, aż stanie się zero, nie będzie żadnego procesora do obsługi wywołań zwrotnych. Podobnie, jak sądzę, używając pewnej formy semaforu. Czy istnieje nieblokujący sposób czekania, aż otrzymam wszystkie odpowiedzi? (Zmiana podpis metody, aby również wziąć zwrotnego ruszy tylko problem o jeden poziom wyżej, boję).

[Edytuj] Oto bardzo blisko pytanie - How to invoke async operation as sync? - ale muszę czekać na wielokrotności asynchronicznym operacje.

Odpowiedz

3

Do tego służy AutoResetEvent.

Spróbuj wykonać następujące czynności dla ostatnich dwóch liniach:

var waitEvent = new AutoResetEvent(false); 

foreach (var item in list) 
    InvokeAsync(item, url, response => { lock(lockObj) newList.Add(response); waitEvent.Set(); }); 

while (newList.Count < list.Count) 
    waitEvent.WaitOne(); 

Wszystkie elementy powinny być zakończone, gdy newList zawiera jak najwięcej przedmiotów, jak list. Gdy pojawi się nowy element, dodajesz go do newList. Następnie sygnalizujesz waitEvent, że "coś" stało się z newList.

W głównym wątku po prostu czekasz, aż masz wystarczającą ilość rzeczy w newList i czekasz na to, czekając na zmiany do newList, o którym informuje Cię waitEvent.

+0

Dziękujemy! Kocham tę stronę. –

+0

Nie ma za co. –

0

Zgodnie z protokołem HTTP klient może otworzyć tylko 2 połączenia z usługą.

+0

http://blogs.msdn.com/b/wenlong/archive/2009/02/08/why-only-two-concurrent-requests-for-load-testing.aspx zgadza się z Tobą, ale wskazuje sposób naprawy że; Planuję skorzystać z sugerowanego rozwiązania, jeśli trafię na to ograniczenie. –

+0

Protokół HTTP nie ma ogólnego limitu dla połączeń, ale ma 2 połączenia (lub 2 razy więcej niż liczba klientów dla serwera proxy lub kodu bramy) jako POWINNY nie bez powodu; w większości przypadków 2 na serwer jest najbardziej wydajną liczbą otwartą na raz. .NET wymusza to, ale można go konfigurować. –

Powiązane problemy