2010-05-06 9 views
12

Mam niezarządzaną bibliotekę DLL z funkcją, która może działać przez długi czas, jeśli parametr wejściowy jest dużą wartością, czasami jest to pożądane, ale nie zawsze.Przerwij połączenie z niezarządzanym DLL

Jak mogę w C# wywołać tę funkcję, aby w razie potrzeby móc ją przerwać?

Do tej pory próbowałem umieścić wywołanie w osobnym wątku, ale żadne przerwanie ani przerwanie nie wydaje się zatrzymywać procesu, który działa na 100% procesorze, dopóki biblioteka DLL nie zostanie wykonana.

Czy można zakończyć działanie kodu dll?

Odpowiedz

23

Kod niezarządzalny można przerwać tylko wtedy, gdy jest to "stan wyczekiwania". Nie będzie, gdy płonie 100% cykli procesora. P/Invoking TerminateThread działałby, zakładając, że możesz uzyskać uchwyt wątku, który .NET bardzo utrudnia. To i tak nie pomoże, przeciekasz stos wątków. Przy jednym megabajtach szybko zabraknie pamięci wirtualnej. Nawet jeśli jest to tylko okazjonalna potrzeba, nadal możesz napotkać poważne problemy, ponieważ wątek zmutował globalny stan programu i nie wiesz, jak go przywrócić.

Jedynym dobrym sposobem na przerwanie niezarządzanego kodu jest uruchomienie go w oddzielnym procesie i zestrzelenie go w głowę za pomocą Process.Kill(). System operacyjny oczyści szrapnel. Musisz napisać mały program hostingowy dla biblioteki DLL i skorzystać z jednego z procesów interopowych, aby z nim porozmawiać. Gniazda, nazwane potoki, .NET remoting, WCF, wybierz.

+4

+1 za wzmiankę o head-shot;) – Nate

+1

Inną opcją jest zrobić to samo w oddzielnej domenie aplikacji. –

+1

Nie, domeny aplikacji nic nie znaczą dla niezarządzanego kodu. –

4

Z MSDN

Jeśli Abort nazywa na zarządzanym wątku podczas jego wykonywania kodu niezarządzanego, ThreadAbortException nie jest wyrzucane aż powróci do gwintów zarządzanego kodu .

Wygląda na to, że przerwanie zarządzanego wątku nie jest możliwe.
Alternatywnie można spróbować uruchomić niezarządzany wątek za pomocą interfejsów API Win32 CreateThread(), WaitForSingleObject() i TerminateThread(). Użyj podpisów od here.

Ja sam tego nie próbowałem, ale z pewnością wprowadza pewne ryzyko, ponieważ nie można ustalić, w którym momencie egzekucji zabija się wątek. Może to również prowadzić do przecieków zasobów. MSDN wymienia niektóre z efektów ubocznych na referencji TerminateThread().

Ogólnie odradzam tego rodzaju zakłócenia. Być może masz możliwość zmiany niezarządzanej biblioteki DLL, aby umożliwić płynne przerywanie.