2009-06-10 14 views
7

Mam wątek, który wychodzi i próbuje nawiązać połączenie. W wątku nawiązuję połączenie z biblioteką strony trzeciej. Czasami połączenie to zawiesza się i nigdy nie wraca. W wątku UI chcę móc anulować próbę połączenia, przerywając wątek, który powinien przerwać zawieszone wywołanie do biblioteki strony trzeciej.Jak radzisz sobie z wątkiem, który ma zawieszone połączenie?

Zadzwoniłem do Thread.Abort, ale przeczytałem teraz Thread.Abort działa tylko wtedy, gdy kontrola powraca do zarządzanego kodu. Zauważyłem, że to prawda, ponieważ wątek nigdy się nie kończy, a ja siedzę na Thread.Join przez dziesięć minut. Co powinienem zrobić z tym zawieszonym wątkiem? Czy powinienem po prostu odrzucić odwołanie i przejść dalej? Chciałbym być tak czysty, jak to możliwe -

Odpowiedz

3

Ta funkcja w bibliotece stron trzecich nie ma limitu czasu funkcji lub anulować? Jeśli tak, to całkiem kiepski projekt. Tu nie będzie żadnego ładnego rozwiązania, metinks ...

Niestety, nie ma sposobu, aby ominąć to, nie używając Win32 API do zabicia wątku ręcznie, co z pewnością jest nie będzie czysty. Jeśli jednak ta zewnętrzna biblioteka nie oferuje żadnych innych opcji, może to być rzeczą do zrobienia. Funkcja TerminateThread jest tym, czego chcesz używać, ale przestrzegaj ostrzeżenia! Aby uzyskać identyfikator wątku do przekazania do tej funkcji, musisz użyć innego wywołania interfejsu Win32 API (klasa Thread nie ujawnia go bezpośrednio). Podejściem tutaj będzie ustawienie wartości niestabilnej zmiennej klasy na wynik GetCurrentThreadId na początku metody zarządzanego wątku, a następnie użycie tego identyfikatora wątku później, aby zakończyć wątek.

4

Losowe myśli: Zastanawiam się, czy mógłbyś napisać drugi zestaw jako małą konsolę exe, która wykonuje tę komunikację ... uruchom ją za pomocą Process.Start i przechwytuj wyniki przez system plików lub przechwytując standardowe wyjście. Jeśli się zawiesza, możesz zabić proces.

Trochę ostry, być może - i oczywiście ma narzuty tarcia procesu - ale przynajmniej powinno być możliwe zabicie go.

+4

"Zdejmij i zniszcz witrynę z orbity - to jedyny sposób, by się upewnić". Rzeczywiście masz rację; jest to jedyny gwarantowany bezpieczny sposób na zakończenie nieprawidłowego kodu. Thread.Abort nie ma gwarancji, że faktycznie przerwie niewłaściwie rozwijający się wątek; naprawdę źle zachowana nić może przejąć kontrolę nad przerwaniem. Nawet usunięcie aplikacji nie zawsze robi to, co chcesz. Jeśli absolutnie, pozytywnie musisz zabić źle zachowany kod, musisz go wyizolować do procesu, który można usunąć. –

+0

Dzięki Ripley ... To znaczy ... Eric ;-p (dałbym odpowiedź Hudsona, ale musiałbym wtedy użyć narzędzi moderatora na sobie ...) –

1

Zarządzane wątki nie mogą bezpośrednio zatrzymać natywnych wątków. Jeśli więc połączenie jest zablokowane w natywnym kodzie, to najlepszą rzeczą, jaką możesz zrobić, jest sprawdzenie wątku zarządzanego, a następnie zakończenie po jego powrocie. Jeśli nigdy nie wróci, być może istnieje wersja połączenia z określonym czasem?

Jeśli nie, zabijając wątek (poprzez win32) zwykle nie jest dobrym pomysłem ...

+0

połączenie nigdy nie wraca, dlatego mam sztucznie zakończyć wątek. – MedicineMan

2

Nie jestem pewien, czy to zrobi, czy będzie do przyjęcia, ale warto spróbować.

[DllImport("kernel32.dll")] 
private static extern bool TerminateThread (Int32 id, Int32 dwexit); 

Z documentation

TerminateThread jest niebezpieczna funkcja, która powinna być stosowana tylko w najbardziej ekstremalnych przypadkach. Powinieneś zadzwonić do TerminateThread tylko wtedy, gdy dokładnie wiesz, co robi docelowy wątek, i kontrolujesz cały kod, który docelowy wątek mógł być uruchomiony w momencie zakończenia. Na przykład TerminateThread może spowodować następujące problemy:

  • Jeśli wątek docelowy jest właścicielem sekcji krytycznej, sekcja krytyczna nie zostanie zwolniona.
  • Jeśli wątek docelowy przydziela pamięć ze sterty, blokada sterty nie zostanie zwolniona.
  • Jeśli wątek docelowy wykonuje pewne wywołania jądra, gdy jest zakończony, stan jądra dla procesu wątku może być niespójny.
  • Jeśli docelowy wątek manipuluje stanem globalnym współużytkowanej biblioteki DLL, stan biblioteki DLL może zostać zniszczony, wpływając na innych użytkowników biblioteki DLL.
-1

Nie jest to dobre rozwiązanie, aby zawsze czekać na wątek (w dowolnym języku) przez czas nieokreślony, zwłaszcza jeśli wykonujesz połączenia zewnętrzne. Zawsze używaj sprzężenia z limitem czasu lub blokady spinu, która monitoruje stan wspólnej zmiennej atomowej, dopóki się ona nie zmieni lub osiągniesz limit czasu. Nie jestem facetem z C#, ale są to praktyki z rozsądną współbieżnością.

+0

czy nawet przeczytałeś pytanie: –

+0

Pewnie - dzięki. – Gandalf

Powiązane problemy