Mam usługę windows napisany w C#, który tworzy ciężarówkę wątków i sprawia, że wiele połączeń sieciowych (WMI, SNMP, prosty TCP, http). Podczas próby zatrzymania usługi Windows za pomocą przystawki MSC usług, wywołanie zatrzymania usługi zwraca się względnie szybko, ale proces trwa nadal przez około 30 sekund.Jak prawidłowo zatrzymać wielowątkową usługę Windows .NET?
Podstawowe pytanie brzmi: co może być powodem, dla którego zatrzymanie trwa 30 sekund. Czego mogę szukać i jak go szukać?
Drugim pytaniem jest, dlaczego usługa msc snap-in (kontroler usług) powraca, mimo że proces nadal trwa. Czy istnieje sposób, aby zmusić go do powrotu tylko wtedy, gdy proces zostanie faktycznie zabity?
Oto kod w OnStop metody usługi
protected override void OnStop()
{
//doing some tracing
//......
//doing some minor single threaded cleanup here
//......
base.OnStop();
//doing some tracing here
}
Edycja w odpowiedzi na gwint porządki odpowiedzi
Wielu z was odpowiedziało, że należy śledzić wszystkich moich wątków i następnie je wyczyść. Nie sądzę, że jest to praktyczne podejście. Po pierwsze, nie mam dostępu do wszystkich zarządzanych wątków w jednej lokalizacji. Oprogramowanie jest dość duże z różnymi komponentami, projektami, a nawet bibliotekami zewnętrznymi, które mogą tworzyć wątki. Nie ma sposobu, aby śledzić wszystkie z nich w jednym miejscu lub mieć flagę sprawdzaną przez wszystkie wątki (nawet jeśli mógłbym mieć wszystkie wątki sprawdzające flagę, wiele wątków blokuje takie rzeczy jak semafory.) Gdy blokują, mogą Sprawdź, będę musiał zmusić ich do czekania z limitem czasu, następnie sprawdź tę flagę globalną i poczekaj jeszcze raz).
Flaga IsBackround jest interesującą rzeczą do sprawdzenia. Znowu jednak, jak mogę się dowiedzieć, czy mam jakieś wątki runiczne naokoło? Będę musiał sprawdzić każdą sekcję kodu, który tworzy wątek. Czy jest jakiś inny sposób, może narzędzie, które może mi pomóc znaleźć to.
Jednak proces się kończy. Wydawałoby się tylko, że muszę na coś poczekać. Jednakże, jeśli czekam w metodzie OnStop przez X ilość czasu, to proces trwa około 30 sekund + X, aby zatrzymać. Niezależnie od tego, co próbuję zrobić, wydaje się, że proces wymaga około 30 sekund (nie zawsze jest to 30 sekund, może się różnić) po powrocie OnStop, aby proces rzeczywiście się zatrzymał.
Czy można umieścić w wszystko, aby zatrzymać inne wątki odpowiednio? Czy są to wątki w tle lub wątki pierwszoplanowe? –
Jeśli używasz komponentów, które mogą wewnętrznie tworzyć wątki, najlepiej byłoby, gdyby każdy z nich miał odpowiedni mechanizm zamykania, który można wywołać w OnStop, więc nie musisz bezpośrednio zarządzać ich wątkami. Jeśli nie, lub jeśli nie chcesz zajmować się czystym wyjściem i chcesz natychmiast zakończyć proces, spróbuj wywołać Environment.Exit ... jednak nie jestem pewien, jak SCM zareaguje, gdy usługa zostanie zakończona wysyła polecenie zatrzymania. – DSO