Udostępnij za pośrednictwem


Niszczenie wątków

Aby zakończyć wykonywanie wątku, zazwyczaj używasz modelu anulowania współpracy. Jednak czasami nie można kooperatywnie zatrzymać wątku, ponieważ uruchamia kod innej firmy, który nie jest przeznaczony do kooperatywnego anulowania. W aplikacjach .NET Framework można użyć Thread.Abort metody , aby wymuśnić zakończenie zarządzanego wątku. Po wywołaniu Abort, środowisko uruchomieniowe języka wspólnego zgłasza wyjątek ThreadAbortException w wątku docelowym, który wątek docelowy może przechwycić. (Jednak środowisko uruchomieniowe programu .NET Framework zawsze automatycznie ponownie zwraca wyjątek po catch bloku). Aby uzyskać więcej informacji, zobacz Thread.Abort.

Metoda Thread.Abort rzuca PlatformNotSupportedException podczas wykonywania w .NET Core, .NET 5 i nowszych wersjach. Począwszy od platformy .NET 5, jest ona również oznaczona jako przestarzała (SYSLIB0006), dlatego wywołanie powoduje wygenerowanie ostrzeżenia w czasie kompilacji. Jeśli musisz zakończyć wykonywanie kodu innej firmy przymusowo w nowoczesnych implementacjach platformy .NET, uruchom go w osobnym procesie i użyj polecenia Process.Kill.

Uwaga / Notatka

  • W przypadku wywołania Thread.Abort do przerwania wątku innego niż bieżący wątek, nie wiesz, jaki kod został wykonany lub nie wykonał się, gdy ThreadAbortException zostanie zgłoszony. Nie można również mieć pewności co do stanu swojej aplikacji ani stanu aplikacji i użytkownika, za którego zachowanie jest odpowiedzialna aplikacja. Na przykład wywołanie Thread.Abort może uniemożliwić wykonanie konstruktorów statycznych lub zwolnienie zarządzanych albo niezarządzanych zasobów.
  • Jeśli wątek wykonuje kod niezarządzany, gdy jest wywoływana jego Abort metoda, środowisko uruchomieniowe oznacza go ThreadState.AbortRequested. Wyjątek jest rzucany, gdy wątek powróci do kodu zarządzanego.

Po przerwaniu wątku nie można go ponownie uruchomić.

Metoda Abort nie powoduje natychmiastowego przerwania wątku, ponieważ wątek docelowy może przechwytywać ThreadAbortException i wykonywać dowolne ilości kodu w finally bloku. Możesz wywołać metodę Thread.Join , jeśli musisz poczekać na zakończenie wątku. Thread.Join to wywołanie blokujące, które nie zwraca się, dopóki wątek rzeczywiście nie przestał działać lub opcjonalny czas oczekiwania nie upłynął. Wątek, który został abortowany, może wywołać metodę ResetAbort lub wykonać nieograniczone przetwarzanie w bloku finally, więc jeśli nie określisz limitu czasu, nie jest gwarantowane zakończenie oczekiwania.

Wątki oczekujące na wywołanie Thread.Join metody mogą zostać przerwane przez inne wątki wywołujące metodę Thread.Interrupt.

Obsługa ThreadAbortException

Jeśli oczekujesz, że wątek zostanie przerwany, albo w wyniku wywołania Abort z własnego kodu lub w wyniku zwolnienia domeny aplikacji, w której działa wątek (AppDomain.Unload używa Thread.Abort do zakończenia wątków), wątek musi obsłużyć ThreadAbortException i wykonać końcowe przetwarzanie w finally klauzuli, jak pokazano w poniższym kodzie.

Try  
    ' Code that is executing when the thread is aborted.  
Catch ex As ThreadAbortException  
    ' Clean-up code can go here.  
    ' If there is no Finally clause, ThreadAbortException is  
    ' re-thrown by the system at the end of the Catch clause.
Finally  
    ' Clean-up code can go here.  
End Try  
' Do not put clean-up code here, because the exception
' is rethrown at the end of the Finally clause.  
try
{  
    // Code that is executing when the thread is aborted.  
}
catch (ThreadAbortException ex)
{  
    // Clean-up code can go here.  
    // If there is no Finally clause, ThreadAbortException is  
    // re-thrown by the system at the end of the Catch clause.
}  
// Do not put clean-up code here, because the exception
// is rethrown at the end of the Finally clause.  

Kod czyszczenia musi znajdować się w klauzuli catch lub finally, ponieważ ThreadAbortException jest ponownie zgłaszany przez system na końcu klauzuli finally, lub na końcu klauzuli catch, jeśli nie ma klauzuli finally.

Można uniemożliwić systemowi ponowne wywołanie wyjątku Thread.ResetAbort przez wywołanie metody . Jednak należy to zrobić tylko wtedy, gdy twój własny kod spowodował ThreadAbortException.

Zobacz także