2011-12-21 13 views
6

Ogólnie z usługami zadanie, które chcesz wykonać, powtarza się, może w pętli lub może wyzwalaczem, a może czymś innym.Górna półka - pętle do obsługi

Używam Topshelf do wykonania powtarzanego zadania dla mnie, w szczególności używam funkcjonalności Shelf'ing.

Problem, który mam, to sposób obsługi pętli zadania.

Podczas rozruchu spinania usługę w Topshelf, przekazać mu klasę (w tym przypadku ScheduleQueueService) i wskazać, jakie jest jego metoda Start i to Stop metoda:

Przykład:

public class QueueBootstrapper : Bootstrapper<ScheduledQueueService> 
{ 
    public void InitializeHostedService(IServiceConfigurator<ScheduledQueueService> cfg) 
    { 
     cfg.HowToBuildService(n => new ScheduledQueueService()); 
     cfg.SetServiceName("ScheduledQueueHandler"); 
     cfg.WhenStarted(s => s.StartService()); 
     cfg.WhenStopped(s => s.StopService()); 
    } 
} 

Ale w moja metoda StartService() używam pętli while, aby powtórzyć uruchomione zadanie, ale kiedy próbuję zatrzymać usługę za pośrednictwem usług Windows, nie zatrzymuje się i podejrzewam, że to dlatego, że metoda StartService() nigdy się nie zakończyła, gdy została pierwotnie wywołana.

Przykład:

public class ScheduledQueueService 
{ 
    bool QueueRunning; 

    public ScheduledQueueService() 
    { 
     QueueRunning = false; 
    } 


    public void StartService() 
    { 
     QueueRunning = true; 

     while(QueueRunning){ 
        //do some work 
     } 
    } 

    public void StopService()  
    { 
     QueueRunning = false; 
    } 
} 

jaki jest lepszy sposób to zrobić?

  1. ja uważane za pomocą .NET System.Threading.Tasks uruchomić pracę w czym może zamykając wątek na StopService()

  2. Może użyciu Quartz powtórzyć zadanie, a następnie wyjmij ją.

Myśli?

Odpowiedz

0

Nie wiem dokładnie o Topshelf, ale przy pisaniu standardowej usługi Windows chcesz, aby zdarzenia startowe i stop zakończyły się tak szybko, jak to możliwe. Jeśli wątek początkowy trwa zbyt długo, Windows zakłada, że ​​nie udało mu się na przykład uruchomić.

Aby obejść ten problem, generalnie używam System.Timers.Timer. To jest ustawione, aby wywołać metodę uruchamiania tylko raz w bardzo krótkim czasie (tak, że działa prawie natychmiast). To czyni większość pracy.

W twoim przypadku może to być twoja metoda, która zapętla się. Następnie na początku każdej pętli sprawdź globalną zmienną wyłączania - jeśli jest prawdą, zamykasz pętlę i program może się zatrzymać.

Możesz potrzebować nieco więcej (lub może nawet mniej) złożoności, w zależności od tego, gdzie dokładnie jest błąd, ale ogólna zasada powinna być dobra, mam nadzieję.

Jeszcze raz odrzucę, że ta wiedza nie jest oparta na górnej półce, jsut ogólnego rozwoju usług.

+0

Po tych wszystkich latach, każdy wie, czy tak jest w przypadku Topshelf? Nie ma o tym żadnej wskazówki w dokumentacji Topshelf i staram się zdecydować, czy powinienem systematycznie odradzać nowy wątek lub coś podobnego w WhenStarted() w mojej usłudze. – guillaume31

3

Ogólnie rzecz biorąc, jak sobie z tym poradzę, to zdarzenie Timer, które odpala się kilka chwil po wywołaniu StartService(). Na koniec wydarzenia sprawdziłbym flagę stop (ustawioną w StopService()), jeśli flaga (np. Twój QueueRunning) nie jest tam, to chciałbym zarejestrować pojedyncze zdarzenie na Timerze, aby zdarzyło się to za kilka chwil .

Robimy coś bardzo podobnego w samej Topshelf, podczas odpytywania systemu plików: https://github.com/Topshelf/Topshelf/blob/v2_master/src/Topshelf/FileSystem/PollingFileSystemEventProducer.cs#L80

Teraz wykorzystuje wewnętrzny typ harmonogramu zamiast Timer obiektu, ale ogólnie jest to samo. fiber jest w zasadzie tym wątkiem, który przetwarza wydarzenie.

Jeśli masz dodatkowe pytania, możesz również dołączyć do listy dyskusyjnej Topshelf. Staramy się być na nie bardzo responsywni. http://groups.google.com/group/topshelf-discuss

+0

pierwszy link jest uszkodzony – SteveC

+2

Masz rację SteveC. Naprawiony! – Travis