Decydującym kawałek kodu nie jest wliczony w cenę; w jaki sposób wątek jest uruchamiany i jaka metoda jest uruchomiona. Gdybym miał zgadywać, powiedziałbym, że prawdopodobnie rozpocząłeś wątek, przekazując metodę instancji z Class
. Więc zasadniczo twoja instancja klasy jest nadal zakorzeniona przez działanie wątku. Próbujesz zatrzymać wątek w finalizatorze, ale finalizator nigdy się nie uruchomi, ponieważ instancja nadal jest zrootowana, co prowadzi do sytuacji catch-22.
Wspomniał Pan również, że wątek zawiera niekrytyczny kod, co było uzasadnieniem dla używania Thread.Abort
. To naprawdę nie jest wystarczający powód. Bardzo trudno jest kontrolować, gdzie ThreadAbortException
zostanie wprowadzony do wątku i w rezultacie może spowodować uszkodzenie struktur danych programu, których się nie spodziewałeś.
Użyj nowych mechanizmów cooperative cancellation dołączonych do licencji TPL. Zmień pętlę while (true)
, aby zamiast tego odpytać CancellationToken. Zatwierdź anulowanie w metodzie Dispose
po wdrożeniu IDisposable
. Nie dołączaj finalizatora (destruktora w języku C#). Finalizatory są przeznaczone do czyszczenia niezarządzanych zasobów. Ponieważ nie wskazałeś, że zasoby niezarządzane są w grze, nie ma sensu mieć finalizatora. Nie musisz dołączać finalizatora podczas implementowania IDisposable
. W rzeczywistości uważa się za niewłaściwą praktykę taką, gdy nie jest ona naprawdę potrzebna.
public class Class : IDisposable
{
private Task task;
private CancellationTokenSource cts = new CancellationTokenSource();
Class()
{
task = new Task(Run, cts.Token, TaskCreationOptions.LongRunning);
task.Start();
}
public void Dispose()
{
cts.Cancel();
}
private void Run()
{
while (!cts.Token.IsCancellationRequested)
{
// Your stuff goes here.
}
}
}
Destruktor klasy C# [nie ma gwarancji, że zostanie wywołany] (http://blogs.msdn.com/b/ericlippert/archive/2010/01/21/what-s-the-difference-betweena-a- destructor-and-a-finalizer.aspx). Użyj opcji [Dispose pattern] (http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx) do deterministycznego czyszczenia zasobów. – Romoku
Zamiast wywoływania GC.Collect użyj instrukcji using() http://msdn.microsoft.com/en-us/library/yh598w02.aspx. Generalnie zaleca się, aby nie dzwonić do GC.Collect -> http: // stackoverflow.com/questions/478167/when-is-it-acceptable-to-call-gc-collect – Oliver
Ustawienie zmiennej instancji na 'null' to * nie to samo * co wywołanie destruktora! Właściwie nie ma praktycznie żadnego wpływu na instancję obiektu, tylko jedno mniej odniesienia. –