2011-01-05 11 views
7

Wdrażam moją pierwszą usługę REST w .NET 4 i napotkałem coś nieoczekiwanego. Wydaje się, że nie rozumiem podkreślenia działania ServiceModel firmy Microsoft, ale nie mogłem znaleźć odpowiedzi w tradycyjny sposób.Zastosowanie puli wątków w implementacji usługi .NET REST

Aby wdrożyć moją usługę internetową ja po schodach w tym tutorialu: http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx

Usługa działa. Zaskoczyło mnie to, że Application_BeginRequest i Application_EndRequest w Global.asax są wywoływane przez różne wątki. Patrząc na ślad stosu, wydaje się, że te wątki są oparte na jakiejś puli wątków.

Bez przeprowadzania refaktoryzacji jest to dla nas problem, ponieważ zawsze zakładaliśmy, że pojedyncze żądanie będzie zawsze uruchamiane w tym samym wątku, dzięki czemu zachowaliśmy niektóre zmienne przechowywane w lokalnej pamięci wątku. Zmienne są inicjowane w Application_BeginRequest i wydawane w Application_EndRequest. Wygląda na to, że z ServiceModel nie jest to właściwe podejście.

Moje pytania są następujące:

  1. mogę dokonywać żadnych założeń, o których wątki są uruchomione mojego kodu gdy używam ServiceModel?
  2. Czy istnieje sposób ograniczenia wykonywania do pojedynczego wątku? Czy byłoby to z jakiegoś powodu złe?
  3. Jaki jest właściwy sposób przechowywania zmiennej przez czas trwania żądania przy korzystaniu z ServiceModel?

Dziękuję.

+0

Aktualizacja do pierwszego pytania. Jest to jeden wątek wywołujący Application_BeginRequest i inny wątek uruchamiający kod usługi i wykonujący Application_EndRequest. Zmiana parametrów usługi ServiceBehavior nic nie dała. Każda pomoc byłaby bardzo cenna. – Alex

+0

Wygląda na to, że używasz kompatybilności asp.net lub próbujesz. Czy próbowałeś zaimplementować swoje rzeczy jako dyspozytorów komunikatów, czy jakikolwiek inny punkt rozszerzenia wcf (zamiast korzystania z asp.net)? – sisve

+0

@Simon Svensson Podążałem za tutorialem Microsoft http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx. Które wydaje się używać kompatybilności asp.net. Co by było inaczej, gdyby zastosowano inne podejście? Czy jest dobre miejsce, w którym mógłbym to przeczytać? Dzięki! – Alex

Odpowiedz

0

Możesz zajrzeć do atrybutu [ServiceBehavior] w implementacji usług, ponieważ obsługuje on argumenty, aby kontrolować liczbę utworzonych instancji i jaki model wątków jest używany.

http://msdn.microsoft.com/en-us/library/cc681240.aspx

Kiedy masz

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
       ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyService : IMyService 

usługę będzie działał jako pojedyncza, ale z wielu wątków - do progu określonego w config WCF - wezwanie do swoich metod. Aby zmusić go do uruchomienia tylko jednego wątku, a następnie przekształceniażądań przychodzących, należy ustawić ConcurrencyMode.Single.

Alternatywnie, można kręcić nową instancję usługi dla każdego połączenia:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, 
       ConcurrencyMode = ConcurrencyMode.Single)] 
public class MyService : IMyService 

Instancja będzie miał tylko jeden wątek dostępu do niego. W rzeczywistości, gdy masz InstanceContextMode.PerCall, wtedy ConcurrencyMode jest ignorowane, ponieważ zawsze jest "Single", a każda instancja działa w swoim własnym wątku.

+0

Dzięki Lawrence. mam ustawione [ServiceBehavior (InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] jeszcze nazywając Thread.CurrentThread.GetHashCode(). ToString() na Application_BeginRequest i Application_EndRequest zwraca inny wartości, czy robię coś niewłaściwie? – Alex

2

Jedną z rzeczy, które sugeruję, jest rozważenie użycia haków WCF zamiast metod Application_BeginRequest i Application_EndRequest. Cztery przykład, tutaj są cztery z bardziej przydatnych haków:

AfterReceiveRequest -> BeforeCall -> wywołanie metody -> AfterCall -> BeforeSendReply

Nie haki są dość silne. Sprawdzasz parametry przed wywołaniem metody (scentralizuj niektóre rejestrowanie w jednym miejscu) i wykonuj wiele innych użytecznych rzeczy.To nie są jedyne dostępne haczyki, ale są też inne, których używam. Na przykład GetInstance pozwala mi przesłonić tworzenie obiektu klasy usług (dzięki czemu można korzystać z frameworków wtrysku zależności itp.).

Gdy korzystam z trybu współbieżności na połączenia, te haki oraz samo wywołanie metody ALL zostają wywołane w tym samym wątku. Mam nadzieję że to pomoże. Mogę podać linki do implementacji tych haków, jeśli chcesz.

Pozdrowienia

Powiązane problemy