W witrynie MSDN opis metody Thread.Abort () mówi: „Wywołanie tej metody zwykle kończy wątek”.
Dlaczego nie ZAWSZE?
W jakich przypadkach nie kończy wątku?
Czy są jakieś inne możliwości zakończenia wątków?
W witrynie MSDN opis metody Thread.Abort () mówi: „Wywołanie tej metody zwykle kończy wątek”.
Dlaczego nie ZAWSZE?
W jakich przypadkach nie kończy wątku?
Czy są jakieś inne możliwości zakończenia wątków?
Odpowiedzi:
Thread.Abort()
wstrzykuje a ThreadAbortException
na nitkę. Wątek może anulować żądanie, dzwoniąc Thread.ResetAbort()
. Istnieją również pewne części kodu, takie jak finally
blok, który zostanie wykonany przed obsłużeniem wyjątku. Jeśli z jakiegoś powodu wątek utknie w takim bloku, wyjątek nigdy nie zostanie zgłoszony w wątku.
Ponieważ wywołujący ma bardzo małą kontrolę nad stanem wątku podczas wywoływania Abort()
, generalnie nie jest to zalecane. Zamiast tego przekaż wiadomość do wątku żądającego zakończenia.
W jakich przypadkach nie kończy wątku?
To pytanie jest powtórzone.
Co jest złego w używaniu Thread.Abort ()
Czy są jakieś inne możliwości zakończenia wątków?
Tak. Twoim problemem jest to, że nigdy nie powinieneś rozpoczynać wątku, którego nie możesz grzecznie przerwać, i kończy się on w odpowiednim czasie. Jeśli jesteś w sytuacji, w której musisz uruchomić wątek, który może być (1) trudny do zatrzymania, (2) błędny lub najgorszy (3) wrogi dla użytkownika, to właściwą rzeczą jest nowy proces, uruchom wątek w nowym procesie, a następnie zakończ proces, gdy chcesz, aby wątek został wyłączony. Jedyną rzeczą, która może zagwarantować bezpieczne zakończenie niewspółpracującego wątku, jest wstrzymanie całego procesu przez system operacyjny.
Zobacz moją zbyt długą odpowiedź na to pytanie, aby uzyskać więcej informacji:
Używanie instrukcji lock w pętli w C #
Istotnym fragmentem jest fragment na końcu, w którym omawiam rozważania dotyczące tego, jak długo należy czekać, aż wątek sam się zabije, zanim go przerwiesz.
Dlaczego nie ZAWSZE? W jakich przypadkach nie kończy wątku?
Na początek wątek może przechwycić ThreadAbortException
i anulować własne zakończenie. Lub może wykonać obliczenia, które trwają wiecznie, gdy próbujesz je przerwać. Z tego powodu środowisko wykonawcze nie może zagwarantować, że wątek zawsze zakończy się, gdy go o to poprosisz.
ThreadAbortException
ma wiecej:
Gdy wywoływana jest metoda Abort w celu zniszczenia wątku, środowisko uruchomieniowe języka wspólnego zgłasza ThreadAbortException. ThreadAbortException to specjalny wyjątek, który można przechwycić, ale zostanie on automatycznie zgłoszony ponownie na końcu bloku catch. Gdy ten wyjątek zostanie zgłoszony, środowisko uruchomieniowe wykonuje wszystkie ostatnie bloki przed zakończeniem wątku. Ponieważ wątek może wykonać nieograniczone obliczenia w
Thread.ResetAbort()
końcowych blokach lub wywołać anulowanie przerwania, nie ma gwarancji, że wątek kiedykolwiek się zakończy.
Nie musisz Abort()
ręcznie zakładać wątku. CLR wykona całą brudną robotę za Ciebie, jeśli po prostu pozwolisz metodzie w wątku powrócić; to zakończy wątek normalnie.
Co się stanie, jeśli wątek zawiera blokadę i zostanie przerwany / zabity? Zasoby pozostają zablokowane
Działa dobrze, gdy wątek wywołuje przerwanie, ale nie inny wątek. Przerwij, wymuszenie kończy wątek, którego dotyczy problem, nawet jeśli nie ukończył zadania i nie daje możliwości wyczyszczenia zasobów
odniesienie MSDN
Nie mogę przerwać wątku, który utknął w pętli:
//immortal
Thread th1 = new Thread(() => { while (true) {}});
Mogę jednak przerwać wątek, jeśli śpi podczas pętli:
//mortal
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }});
ThreadAborts nie wystąpi wewnątrz bloku Final lub między BeginCriticalRegion i EndCriticalRegion
Ponieważ możesz złapać ThreadAbortException
i wywołać Thread.ResetAbort
wewnątrz handlera.
OT: Aby zapoznać się z obszernym, niezależnym od języka, wątpliwie użytecznym i cholernie zabawnym podejściem do współbieżności, zobacz Verity Stob !
Miałem przypadki, w których wątek był zbyt zajęty, aby usłyszeć wywołanie Abort (), co zwykle powoduje zgłoszenie wyjątku ThreadAbortingException do mojego kodu.