[C#] Thread management

Pagina: 1
Acties:

Onderwerpen


Verwijderd

Topicstarter
Dag allemaal,
Ik sit vast met een hoe het correct beeindigen van een thread, meerbepaald 2 theads.

Ik hoop dat dit duidelijk is:
-2 theads die gebruikmaken van éénzelfde object om een stuk code te locken
-bijde threads hebben een AutoResetEvent
-bij de aanvraag van het stuiten van de applicatie roep ik AutoResetEvent.Set voor de twee threads

Bij dit laatse puntje is het probleem, roep ik deze 2 Set methodes op dan zal de code in de thread niet meer runnen (zie while loop in code) maar hiermee zijn de threads nog niet beeindigd en ik heb ook opgemerkt dat dat één van de 2 thead of beiden nog bezig kunnen zijn met het verwerken van data na ik de Set method op opgeroepen. Moet ik nu abort, join opreopen na de Set of moet het anders.

Een stuk code ter verduidelijking :
C#: geen
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
private static object _OLock = new object();
private static AutoResetEvent threadWait = new AutoResetEvent(false);
private static AutoResetEvent threadWaitCleanup = new AutoResetEvent(false);

private static void DoWork()
{
            bool mainLoop = true;

            while (mainLoop && !threadWait.WaitOne(Config.SleepTimeFtpThread))
            {
                Console.Write(".");
                lock (_OLock)
                {....}
            }
}

private static void CleanUp()
        {
            bool mainLoop = true;

            while (mainLoop && !threadWaitCleanup.WaitOne(Config.SleepTimeCleanupThread))
            {
                Console.Write(".");
                lock (_OLock)
                {...}
            }
}

public static void StopThreads()
{

            Console.WriteLine("\r\nStopping all threads...");

            /* Stopping DoWork */
            threadWait.Set();
            /* Stopping CleanUp */
            threadWaitCleanup.Set();

            Console.WriteLine("Threads stopped.");
            Console.WriteLine("Its safe to close application.");
}

  • Korben
  • Registratie: Januari 2001
  • Laatst online: 13-07 01:53

Korben

() => {};

Abort moet je sowieso nooit aanroepen tenzij je een thread echt op brute wijze wilt beëindigen.

Aan te raden zou zijn om na het aanroepen van Set() een Join() op die thread aan te roepen, mits je een reference naar die Thread hebt. Een andere oplossing zijn om twee AutoResetEvents per thread te gebruiken; één waarmee je aangeeft dat de thread moet stoppen en één waarmee de thread aangeeft dat hij klaar is. Vervolgens roep je WaitHandle.SignalAndWait() aan (improvisatie op jouw code):

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static AutoResetEvent _exitSignal = new AutoResetEvent(false);
private static AutoResetEvent _threadExited = new AutoResetEvent(false);

void ThreadMethod()
{
    bool running = true;

    while (running && _exitSignal.WaitOne(Config.SleepTimeFtpThread))
    {
        Console.Write(".");
    }

    _threadExited.Set();
}

static void Stop()
{
    WaitHandle.SignalAndWait(_exitSignal, _threadExited);
    // dit signalt _exitSignal en wacht vervolgens tot _threadExited gesignalt wordt in een atomische bewerking
}

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


Verwijderd

Topicstarter
Voor jouw eerste methode, roep ik Join op in de StopTheads methode of in de thead methodes zelf? (Vermits je over reference heb dacht ik dat je het over punt 2 hebt in mijn zin.)

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Verwijderd schreef op donderdag 12 augustus 2010 @ 10:11:
Voor jouw eerste methode, roep ik Join op in de StopTheads methode of in de thead methodes zelf? (Vermits je over reference heb dacht ik dat je het over punt 2 hebt in mijn zin.)
In StopThreads. Ik snap trouwens niet het voordeel van de tweede methode, dus Join lijkt me het beste. Daarnaast kun je met 1 ManualResetEvent volstaan, in plaats van meerdere AutoResetEvents. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • Korben
  • Registratie: Januari 2001
  • Laatst online: 13-07 01:53

Korben

() => {};

Als ik het over een reference naar de thread heb, dan bedoel dat je ergens in je code dit hebt staan:

C#:
1
2
3
4
5
6
7
8
9
private static Thread _ftpThread;

// ...

void Start()
{
    _ftpThread = new Thread(/* ... */);
    _ftpThread.Start();
}


Join() roep je in ieder geval aan in de StopThreads method, Join() wacht namelijk tot de thread waar je hem op aanroept beëindigt is. Als je dat vanuit de thread zelf doet, zal die nooit eindigen.

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


Verwijderd

Topicstarter
Ok ik snap het. Beetje sheef aant lezen. Het komt zo raar voor dat ik zelf eens threads gebruikt.

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Ter informatie: C# heeft tegenwoordig een veruit superieure oplossing boven het handmatig klooien met threads, wait handles, etc.

Neem eens een kijkje in de keuken van System.Threading.Tasks, waar je dit specifieke probleem elegant en simpel mee op kunt lossen: Task Cancellation

Zolang het hier niet legacy code betreft (die niet in aanmerking komt voor een upgrade), zou ik snel van bare-bones threads af stappen.

  • pedorus
  • Registratie: Januari 2008
  • Niet online
R4gnax schreef op donderdag 12 augustus 2010 @ 20:43:
Neem eens een kijkje in de keuken van System.Threading.Tasks,
Prima idee.
waar je dit specifieke probleem elegant en simpel mee op kunt lossen: Task Cancellation
Task Cancellation gebruiken om gewoon iets af te ronden is dan weer een vreemde suggestie, om dezelfde reden dat je in een normale situatie geen exceptions gooit. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
pedorus schreef op donderdag 12 augustus 2010 @ 21:09:
[...]

Prima idee.

[...]

Task Cancellation gebruiken om gewoon iets af te ronden is dan weer een vreemde suggestie, om dezelfde reden dat je in een normale situatie geen exceptions gooit. :p
Kijk eens naar de code listing in de opening post. Het betreft volgens mij het afsluiten van twee periodiek uit te voeren processen in parellele worker threads, alvorens de algehele applicatie afgesloten wordt. Dat is mijns inziens toch een taak voor Task Cancellation: de twee worker threads zijn tasks die niet eindigen, maar zichzelf om de zoveel tijd herhalen. Ze kunnen dus slechts eindigen in een cancelled status, en niet in een complete status.

  • pedorus
  • Registratie: Januari 2008
  • Niet online
R4gnax schreef op donderdag 12 augustus 2010 @ 22:03:
de twee worker threads zijn tasks die niet eindigen, maar zichzelf om de zoveel tijd herhalen. Ze kunnen dus slechts eindigen in een cancelled status, en niet in een complete status.
Dus als je repeterend werk doet kan het nooit af zijn? ;) Verder kan ik wegens gebrek aan informatie niet zeker zeggen wat hier de juiste eindstatus is. Maar zo op het eerste gezicht zou ik gewoon wachten op een completion-event, niet op de waithandle van een cancellationtoken. Al is het maar omdat een ManualResetEvent net iets minder code/overhead oplevert.

Niettemin zou het best kunnen dat het hele gebeuren met Tasks kan worden herschreven.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1