2009-08-14 9 views
10

Uruchamiamy aplikację konsoli C#, która uruchamia wiele wątków w celu wykonania pracy. Główną funkcją wygląda mniej więcej tak:Aplikacja C# niespodziewanie się kończy

try 
{ 
    DoWork(); 
} 
catch (Exception err) 
{ 
    Logging.Log("Exception " + err.ToString()); 
} 
Logging.Log("Finished"); 

Funkcja DoWork() czyta nowych miejsc pracy z bazy danych, a ikra wątki przetwarzać jeden element pracy każdego. Od zeszłego tygodnia aplikacja zaczęła znikać w tajemniczy sposób. Znika z listy procesów i nie ma wpisu w dziennikach zdarzeń. Plik dziennika pokazuje pracę do pewnego momentu: nie rejestruje wyjątku ani linii "Zakończono".

Wszelkie wskazówki na temat tego, jak aplikacja C# może zniknąć w ten sposób?

EDIT: Nici są tworzone jak:

new Thread(SomeObj.StartFunc).Start(); 

Niektóre zaginięć wystąpić gdy nie ma wątków są uruchomione.

P.S. Zainstalowaliśmy DebugDiag z regułą, aby utworzyć zrzut awaryjny za każdym razem, gdy nasz program się zawiesił. Nie tworzyło żadnych plików zrzutu, gdy proces zniknął.

+0

Moglibyśmy naprawdę zrobić z bardziej szczegółowymi informacjami na temat tego, co jest w metodzie DoWork ... –

+0

Co robi DoWork po utworzeniu i uruchomieniu wątków? Czy wchodzi w nieskończoną pętlę, natychmiast wychodzi, próbuje dołączyć do wątków tła, czy co? –

+0

Przechodzi w nieskończoną pętlę. Wątki w tle aktualizują swój status w tablicy, która jest chroniona za pomocą instrukcji lock {}. Po zakończeniu wątku usuwa swój własny wpis z tablicy. – Andomar

Odpowiedz

9

Jaką tożsamość używasz do uruchamiania aplikacji konsolowej?

Możesz również użyć SetConsoleCtrlHandler do przechwytywania zdarzeń konsoli. Spójrz na to blog po więcej szczegółów. Podobny problem wystąpił, gdy aplikacja Console była uruchamiana pod kontem usługi, co jakiś czas została rozwiązana. Nie jestem pewien, czy to jest to, na co się natknąłeś. Daj mi znać, że mogę opublikować kod.

AKTUALIZACJA: Wygląda na to, że scenariusz przypomina to, czego doświadczyliśmy. W konsoli obsługi zdarzeń konsoli musisz sprawdzić zdarzenie LogOff i zwrócić wartość true. Spójrz na to KB artykule

public static void inputHandler(ConsoleCtrl.ConsoleEvent consoleEvent) 
{ 
    if (ConsoleEvent == ConsoleCtrl.ConsoleEvent.CtrlLogOff) 
     return true; 
    return false; 
} 
+0

Jest uruchamiana jako zaplanowane zadanie przez konto z uprawnieniami administratora. Dodałem funkcję obsługi i zmodyfikowałem ją, aby rejestrować zdarzenia, pozwalając jej działać przez jakiś czas, aby sprawdzić, czy trafi! – Andomar

+2

Dodałem rejestrowanie, a zdarzenie CtrlLogOff rzeczywiście powoduje zakończenie zaplanowanego zadania. Problem rozwiązany, ale chcielibyśmy się dowiedzieć, skąd pochodzi wydarzenie CtrlLogOff! – Andomar

+5

Jak to możliwe, że zwracasz wartość boolean z funkcji void? – Ruud

9

Musisz mieć podobny blok catch na najwyższym poziomie funkcji, którą obsługuje każdy wątek. Jeśli na wątku pojawi się nienaruszony wyjątek, zabije aplikację, blok catch na głównym wątku nie pomoże.

+0

Wątek ma blok try/catch w jego funkcji najwyższego poziomu. – Andomar

3

Być może jest to funkcja Logging.Log, która zgłasza wyjątek?

+0

Funkcja rejestrowania jest prosta i dostępna jest duża ilość miejsca na dysku. Program utrzymuje otwarty pojedynczy StreamWriter podczas działania i chroni dostęp do niego za pomocą sekcji lock {}. – Andomar

3

Program konsoli zostaje zamknięty po wyjściu z funkcji głównej. Ponieważ DoWork tworzy tylko kilka wątków, przywraca kontrolę główną, a ponieważ Main nie ma już nic do roboty, kończy działanie i program się kończy. W tym czasie wątki spawnowane przez DoWork również zostają zabite.

To, co zadziałało wcześniej oznacza, że ​​w DoWork() było coś, co czekało na te wątki, które teraz wracają od razu (są zepsute) lub ta część nadal działa, ale wątek, który dawno temu wracał, teraz przerywa i wraca od razu.

+0

Funkcja DoWork() nie powraca przed wykonaniem wszystkich prac i wszystkie wątki zostały zamknięte. Program sprawował się dobrze przez lata i przetworzył ponad milion pozycji roboczych. – Andomar

+0

Czekaj ... Myślałem, że tylko wątki w tle zostaną zabite, gdy aplikacja, która je zainicjowała, opuści? – Will

+0

@Will: Myślę, że to zachowanie dla usługi Windows. Inne aplikacje Windows działają tak, jak Joel opisuje – Andomar

2

Udało mi się sprawić, że programy znikają bez śladu w podobny sposób do ciebie (żadnych śladów wyjątków, żadnych komunikatów z dziennika zakończenia) w przeszłości. Niemal cały czas było to związane z zabijaniem stosu (nazwa tej strony zawsze mi przypomina).

Czy to możliwe, że nagle próbujesz przetworzyć znacznie więcej danych niż zwykle lub używając procedur ponownego wpisywania, lub będąc "sprytnymi" ze wskaźnikami?

ZASTRZEŻENIE: moje doświadczenie było związane z aplikacją Win32 C++, a nie C#.

2

Czy to może być wyciek pamięci? Jeśli twoja aplikacja zajmuje zbyt dużo pamięci, Windows ją zabije. Możesz sprawdzić, ile pamięci używasz: jeśli rośnie z upływem czasu, możesz mieć wyciek pamięci.

Inną możliwością jest to, że gdzieś masz kod wywołujący Environment.Exit(). Spróbuj przeszukać cały tekst za pomocą kodu, aby dokładnie sprawdzić, nigdy nie wiesz!

+0

Dzięki za porady. Wydaje się, że użycie pamięci nie wzrasta, a funkcja Exit() była jedną z pierwszych rzeczy, które sprawdziliśmy :) – Andomar

5

Jest możliwe, że jeden z wątków, do których spawana jest metoda DoWork, rzuca wyjątek. Domyślnym zachowaniem w tym przypadku jest zakończenie procesu. Możesz zatrzymać to zdarzenie, używając zdarzenia AppDomain.UnhandledException, aby zastąpić domyślne zachowanie.

2

być ostrożnym, istnieją pewne wyjątki, które nie mogą zostać złapane: OutOfMemoryException, StackOverflowException, dlatego program umrze strasznie, ale cicho.

+0

Tak, ale spodziewam się, że spowoduje to wywołanie DebugDiag i zarejestrowanie zrzutu awaryjnego. – Andomar

+0

AFAIK 'OutOfMemoryException' może zostać przechwycony. – CodesInChaos

Powiązane problemy