11/11/2014

Domeny aplikacyjne i wątki


Jakiś czas temu odpowiedziałem na pytanie na stackoverflow.com dotyczące kończenia pracy wątków z zewnętrznej biblioteki w sytuacji kiedy powinny już zakończyć pracę, a jednak tego nie zrobiły. Moja odpowiedź została co prawda skrytykowana, zresztą słusznie, ale dzięki temu dowiedziałem się rzeczy, która mi wcześniej umknęła.

W mojej odpowiedzi zasugerowałem, że skoro z jakiegoś powodu musimy użyć zewnętrznej biblioteki i ona nie działa to ja bym ją załadował do oddzielnej domeny aplikacyjnej i w tej nowej domenie uruchomił też obliczenia (wątki). Taką domeną można natomiast w dowolnym momencie "odładować" przy pomocy AppDomain.Unload. Napisałem nawet przykład pokazujący, że to działa. W czym więc problem?

Otóż wywołanie AppDomain.Unload może się nie powieść i zostanie wtedy rzucony wyjątku CannotUnloadAppDomainException. Powodów mogą być trzy, ale nas interesuje jeden. Kiedy wołamy AppDomain.Unload i wewnątrz domeny są aktywne jakieś wątki to AppDomain.Unload spróbuje je ubić przy pomocy metody Thread.Abort. Jeśli się uda to ok, ale Thread.Abort może nie być w stanie ubić wątku i wtedy zostanie wygenerowany wzmiankowany powyżej wyjątek.

Kiedy Thread.Abort nie zadziała? Dokumentacja wspomina o dwóch przypadkach.
  • Kiedy wątek wykonuje kod niezarządzany.
  • Kiedy wątek wykonuje właśnie kod wewnątrz bloku finally. To można bardzo łatwo symulować przez umieszczenie wywołania Thread.Sleep(100000) wewnątrz bloku finally.

No comments:

Post a Comment