Avatar billede matiasdk Nybegynder
18. april 2006 - 00:51 Der 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())

Hvad er problemet?
Avatar billede matiasdk Nybegynder
18. april 2006 - 00:52 #1
(og hverken destructor eller dispose bliver kaldt)
Avatar billede Syska Mester
18. april 2006 - 00:54 #2
og din Workerthread er færdig med det den skal?
og du har kørt en Dispose/Stop eller hvad den nu kan, på din workerthread?

måske lidt kode......

// ouT
Avatar billede arne_v Ekspert
18. april 2006 - 01:58 #3
følgende virker fint:

using System;
using System.Threading;

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();
            }
        }
    }
}
Avatar billede matiasdk Nybegynder
19. april 2006 - 00:10 #4
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

-------------------------------------------------------------

Problemet er imidlertid, at der ikke sker en disse selvom x-handlet bliver null'et.
Heller ikke hvis jeg laver en GC.Collect();

Hvad er problemet?
Avatar billede arne_v Ekspert
19. april 2006 - 05:12 #5
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");
        }
    }
}
Avatar billede matiasdk Nybegynder
19. april 2006 - 18:50 #6
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.
Avatar billede arne_v Ekspert
19. april 2006 - 19:00 #7
Nej - Dispose skal enten kaldes explicit eller implicit via using

og du faar ikke den traad GC'et foerend den er faerdig med at koere

kan du ikke saette et flag der faar den til at stoppe eller bruge
Abort/INterrupt paa den ?
Avatar billede matiasdk Nybegynder
20. april 2006 - 00:01 #8
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?
Avatar billede arne_v Ekspert
20. april 2006 - 00:13 #9
ja

.NET skal have en reference til tråden for at kunne køre den
Avatar billede matiasdk Nybegynder
20. april 2006 - 10:53 #10
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.

Vil du have point?
Avatar billede arne_v Ekspert
20. april 2006 - 13:09 #11
svar

teknisk set var buzz faktisk først med spørgsmålet om tråden var færdig  !
Avatar billede Syska Mester
20. april 2006 - 17:47 #12
:-)

Giv mig 5 point, så er jeg tilfreds :-)

Arne er kommet med meget god læsning også for mig :-)

// ouT
Avatar billede matiasdk Nybegynder
21. april 2006 - 00:55 #13
Svar
Avatar billede arne_v Ekspert
19. juni 2006 - 01:33 #14
buzz>

du skal nok ligge et svar så
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester