Toon posts:

[C#] Destructor

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben even flink bezig geweest met multi threading in .Net 2.0 & C# en nu zoek ik een manier om mijn applicatie netjes te sluiten (dus niet bruut alle threads killen terwijl ze nog bezig zijn), en heb dat met een Destructor willen oplossen, zie onderstaande voorbeeld code:
Thread.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public abstract class Thread
{
    private System.Threading.Thread workerThread;

    private System.Threading.AutoResetEvent autoResetEvents;

    private bool suspended;

    public Thread(System.Threading.ThreadPriority ThreadPriority)
    {
        workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(Execute));
        autoResetEvents = new System.Threading.AutoResetEvent(false);
        workerThread.Priority = ThreadPriority;
        suspended = true;
    }

    public void Suspend()
    {
        suspended = true;
        this.Signal();
        workerThread.Join();
    }

    public void Resume()
    {
        try
        {
            suspended = false;
            workerThread.Start();
        }
        catch (System.Threading.ThreadStartException tse)
        {
            suspended = true;
            throw tse;
        }
    }

    protected virtual void Execute()
    {
        while (workerThread.IsAlive)
        {
            ExecuteTask();
            autoResetEvents.WaitOne();
            if (suspended) break;
        }
    }

    protected abstract void ExecuteTask();

    protected void Signal()
    {
        autoResetEvents.Set();
    }
}


RequestManager.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface IRequest
{
}

public abstract class RequestManager : Thread
{
    private System.Collections.Generic.Queue<IRequest> requestQueue;

    public RequestManager(System.Threading.ThreadPriority ThreadPriority)
        : base(ThreadPriority)
    {
        requestQueue = new System.Collections.Generic.Queue<IRequest>();
        this.Resume();
    }

    ~RequestManager()
    {
        this.Suspend();
    }

    protected override void ExecuteTask()
    {
        lock(requestQueue)
            while (requestQueue.Count > 0)
                ProcessRequest(requestQueue.Dequeue());
    }

    protected abstract void ProcessRequest(IRequest Request);

    public void AddRequest(IRequest Request)
    {
        lock(requestQueue)
            requestQueue.Enqueue(Request);
        this.Signal();
    }
}


IConsoleWritingRequestManager.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public interface IConsoleWritingRequest : IRequest
{
    string Text
    {
        get;
    }
}

public class ConsoleWritingRequest : IConsoleWritingRequest
{
    private string text;

    public string Text
    {
        get
        {
            return text;
        }
    }

    public ConsoleWritingRequest(string text)
    {
        this.text = text;
    }
}

public sealed class ConsoleWritingRequestManager : RequestManager
{
    private static ConsoleWritingRequestManager instance = null;

    public static ConsoleWritingRequestManager Instance
    {
        get
        {
            if(instance == null)
                instance = new ConsoleWritingRequestManager();
            return instance;
        }
    }

    private ConsoleWritingRequestManager()
        : base(System.Threading.ThreadPriority.BelowNormal)
    {
    }

    protected override void ProcessRequest(IRequest Request)
    {
        if (Request is IConsoleWritingRequest)
        {
            IConsoleWritingRequest ConsoleWritingRequest = (Request as IConsoleWritingRequest);
            System.Console.WriteLine(ConsoleWritingRequest.Text);
        }
    }

    public void Release()
    {
        instance = null;
    }
}


ConsoleeApplication1.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
namespace ConsoleApplication1
{
    
    public class Program
    {
        private ConsoleWritingRequestManager ConsoleWritingRequestManager;

        public Program()
        {
            this.ConsoleWritingRequestManager = ConsoleWritingRequestManager.Instance;
        }

        ~Program()
        {
            this.ConsoleWritingRequestManager.Release();
        }

        public void Go()
        {
            this.ConsoleWritingRequestManager.AddRequest(new ConsoleWritingRequest("Hello world!"));
        }
    
        static void Main(string[] args)
        {
            new Program().Go();
        }
    }
}


Probleem is dat de Program destructor niet wordt uitgevoerd, waardoor de ConsoleWritingRequestManager private static instance een verwijzing houdt waardoor de thread actief blijft en niet wordt opgeruimd, gevolg: applicatie sluit niet netjes. Nu zou ik natuurlijk de Release() kunnen uitvoeren na de Go() of in de Go(), maar dat vind ik een niet zo nette oplossing. Vraag is nu hoe ik kan zorgen dat de destructor wordt aangeroepen.

  • whoami
  • Registratie: December 2000
  • Nu online
Da's geen Destructor, maar een Finalizer. Die Finalizer wordt aangeroepen door de Garbage Collector.
Je weet niet wanneer de GC die zal aanroepen, en je weet ook niet hoeveel keer en wanneer de GC in actie schiet.

Als je zelf dingen wilt opruimen, maak dan gebruik van een Dispose method. Implementeer IDispose, en roep Dispose zelf aan.

Even in de MSDN zoeken op Finalize , Dispose, Dispose pattern.

https://fgheysels.github.io/


Verwijderd

Topicstarter
whoami schreef op donderdag 26 oktober 2006 @ 16:58:
Da's geen Destructor, maar een Finalizer. Die Finalizer wordt aangeroepen door de Garbage Collector.
Je weet niet wanneer de GC die zal aanroepen, en je weet ook niet hoeveel keer en wanneer de GC in actie schiet.

Als je zelf dingen wilt opruimen, maak dan gebruik van een Dispose method. Implementeer IDispose, en roep Dispose zelf aan.

Even in de MSDN zoeken op Finalize , Dispose, Dispose pattern.
Aha, bedankt, die terminologie verwarring zal wel komen door C++, ik zal de Dispose() implementeren.