2015-05-02 15 views
5

Mam usługę systemu Windows, która spawnuje zestaw czynności podrzędnych na osobnych wątkach i powinna zakończyć się dopiero po pomyślnym zakończeniu wszystkich tych działań. Nie wiem z góry, ile czasu może upłynąć, aby zakończyć działanie po otrzymaniu sygnału zatrzymania. Podczas OnStop(), czekam w odstępach czasu na ten sygnał zatrzymania i żądam dodatkowego czasu tak długo, jak system jest skłonny je przyznać.Co to jest bezpieczny narzut dla RequestAdditionalTime()?

Oto podstawowa struktura:

class MyService : ServiceBase 
{ 
    private CancellationTokenSource stopAllActivities; 
    private CountdownEvent runningActivities; 

    protected override void OnStart(string[] args) 
    { 
     // ... start a set of activities that signal runningActivities 
     //  when they stop 
     // ... initialize runningActivities to the number of activities 
    } 

    protected override void OnStop() 
    { 
     stopAllActivities.Cancel(); 

     while (!runningActivities.Wait(10000)) 
     { 
      RequestAdditionalTime(15000); // NOTE: 5000 added for overhead 
     } 
    } 
} 

Podobnie jak wiele „overhead” Powinienem być dodanie w zaproszeniu RequestAdditionalTime? Obawiam się, że żądania są kumulatywne, zamiast opierać się na momencie, w którym wykonywane jest każde wywołanie RequestAdditionalTime. W takim przypadku dodanie narzutu może spowodować, że system ostatecznie odrzuci żądanie, ponieważ jest zbyt daleko w przyszłości. Ale jeśli nie dodaję żadnych kosztów ogólnych, moja usługa może zostać zakończona, zanim będzie mogła poprosić o kolejny blok dodatkowego czasu.

Odpowiedz

5

This post nie było dokładnie zachęcające:

dokumentacji MSDN nie wspomina o tym, ale wydaje się, że wartość określona w RequestAdditionalTime rzeczywistości nie jest „dodatkowy” czas. Zamiast tego zastępuje wartość w usłudze ServicesPipeTimeout. Co gorsza, każda wartość większa niż dwie minuty (120000 milisekund) jest ignorowana, tj. Ograniczona do dwóch minut.

Mam nadzieję, że tak nie jest, ale zamieszczam to jako najgorszą możliwą odpowiedź.

AKTUALIZACJA: Autor tego wpisu był na tyle uprzejmy, aby opublikować bardzo szczegółową odpowiedź na mój komentarz, który skopiowałem poniżej.

Lars, krótka odpowiedź brzmi nie.

To, co chciałbym powiedzieć, to to, że teraz zdaję sobie sprawę, że usługi Windows powinny być zaprojektowane tak, aby szybko rozpoczynać i zakończyć przetwarzanie, gdy zostanie o to poproszony.

Jako programiści koncentrujemy się na implementacji przetwarzania, a następnie pakujemy je i dostarczamy jako usługę Windows.

Jednak to naprawdę nie jest właściwe podejście do projektowania usług Windows. Usługi muszą być w stanie szybko reagować na żądania uruchomienia i zatrzymania nie tylko wtedy, gdy administrator wysyła żądanie z konsoli usług, ale także wtedy, gdy system operacyjny żąda uruchomienia w ramach procesu uruchamiania lub zatrzymania, ponieważ wyłącza się ,

Zastanów się, co stanie się, gdy system Windows zostanie skonfigurowany do wyłączenia, gdy UPS zasygnalizuje awarię zasilania. Nieodpowiednie jest, aby usługa odpowiedziała "Potrzebuję jeszcze kilku minut ...".

Możliwe jest pisanie usług, które reagują szybko, aby zatrzymać żądania, nawet jeśli wykonują długo działające zadania przetwarzania. Zwykle długotrwały proces będzie polegał na przetwarzaniu wsadowym danych, a przetwarzanie powinno sprawdzać, czy wymagane jest zatrzymanie na poziomie najmniejszej jednostki pracy, która zapewnia spójność danych.

Jako przykład, pierwsza usługa, w której znalazłem limit czasu zatrzymania, była problemem związanym z przetwarzaniem kolejki powiadomień na serwerze zdalnym.Przetwarzanie odebrało powiadomienie z kolejki, wywoływanie usługi internetowej w celu pobrania danych związanych z przedmiotem powiadomienia, a następnie zapisanie pliku danych do przetworzenia przez inną aplikację.

Zaimplementowałem przetwarzanie jako wywołanie sterowane zegarem do pojedynczej metody. Po wywołaniu metody nie powraca, dopóki wszystkie powiadomienia w kolejce nie zostaną przetworzone. Zdałem sobie sprawę, że to był błąd dla usługi systemu Windows, ponieważ czasami mogą pojawić się dziesiątki tysięcy powiadomień w kolejce, a przetwarzanie może zająć kilka minut.

Metoda jest w stanie przetworzyć 50 powiadomień na sekundę. Powinienem był więc zaimplementować czek, aby sprawdzić, czy żądanie zostało zatrzymane przed przetworzeniem każdego powiadomienia. Pozwoliłoby to na zwrócenie metody po zakończeniu przetwarzania powiadomienia, ale przed rozpoczęciem przetwarzania następnego powiadomienia. Zapewniłoby to szybkie reagowanie usługi na żądanie zatrzymania, a wszelkie oczekujące powiadomienia pozostawały w kolejce do przetworzenia po ponownym uruchomieniu usługi.