18. april 2006 - 00:51Der er
13 kommentarer og 1 løsning
MyThread.Dispose() bliver ikke kørt når objekt går ud af scope
Jeg har lavet et class der indeholder en workerthread. Når class'en instantiate's, oprettes den interne workerthread. Når class'en går ud af scope, oplever jeg imidlertid, at class'en bliver ved med at eksitere, og at tråden stadigvæk kører. Jeg har oprettet Dispose-metoder samt en destructor (~Classname())
namespace E { public class X : IDisposable { private Thread worker; public X() { worker = new Thread(new ThreadStart(Run)); worker.Start(); } public void Run() { for(int i = 0; i < 10; i++) { Thread.Sleep(500); } } public void WaitToDone() { worker.Join(); } public void Dispose() { Console.WriteLine("Bye bye"); } } public class TestClass { public static void Main(string[] args) { using(X o = new X()) { Console.WriteLine("Started"); o.WaitToDone(); } } } }
Nope, det virker ikke. Jeg havde glemt at tilføje IDisposable, men det afhjalp nu heller ikke problemet at tilføje den. Mht til eksemplet ovenfor, så ligner det meget, bortset fra at jeg også har en destructor ~X(), som heller ikke modtager kald.
Jeg vil gerne at følgende kode afslutter tråden: ----------------------------------------------------------- X x = new X(); x.Start(); System.Threading.Thread.Sleep(10000); x = null; // det her skal være nok
hvis tråden ikker er færdig så skal den jo ikke GC'es
følgende virker hos mig:
using System; using System.Threading;
namespace E { public class X { private Thread worker; public X() { worker = new Thread(new ThreadStart(Run)); worker.Start(); } ~X() { Console.WriteLine("Bye bye"); } public void Run() { for(int i = 0; i < 10; i++) { Thread.Sleep(200); } } public void WaitToDone() { worker.Join(); }
} public class TestClass { public static void Main(string[] args) { X o = new X(); Console.WriteLine("Started"); o.WaitToDone(); o = null; GC.Collect(); Thread.Sleep(100); Console.WriteLine("Ready to end"); } } }
Trådens funktion afslutter aldrig. Derfor skal tråden automatisk bliver lukket ned, gerne af Dispose()-kaldet. Problemet er at Dispose() ikke bliver kaldt automatisk ved "o = null;"
Hvis tråden ikke startet, men objektet bare oprettes, så afsluttes det på forventelig vis. Jeg er som sædvanlig nødt til at lave en GC.Collect() for at teste dette. Problemet er altså bare at der ingenting sker hvis tråden er startet.
Jamen jeg forstår ikke hvorfor destructoren ikke bliver kaldt når referencen til objektet bliver null'et? Det er som om at der stadig findes en ekstern reference til objektet når der kører en tråd, måske et sted i System.Threading namespacet?
Hold da op hvor besværligt. Nu har jeg lavet en container class, og det virker fint, dens destructor logic bliver kaldet fint og derved lukkes tråden, dog først når GC.Collect() bliver kaldt.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.