Hoe een thread opnieuw te starten

Het parallel starten van een functie in een script met threading werkt erg goed, maar heeft ook zijn beperking. Binnen het script is het niet mogelijk dezelfde thread opnieuw te starten. Je krijgt een Runtime error of er ontstaat in een lus in de eerste thread er een onwenselijke tweede, derde, vierde... thread bij. Jason Brownlee heeft uitleg gegeven hoe je dit kunt voorkomen. Ik neem je er in mee. 

Deze tutorial is een aanvulling op de tutorial Functies gelijktijdig uitvoeren met threading.

Daar gaan we!

Je kunt een thread in Python niet opnieuw starten, in plaats daarvan moet je een nieuwe thread maken en starten met dezelfde configuratie.

Een thread opnieuw starten
Elk Python-programma heeft ten minste één uitvoeringsthread, de hoofdthread. Zowel processen als threads worden gemaakt en beheerd door het onderliggende besturingssysteem. Soms moeten we extra threads in ons programma maken om code gelijktijdig uit te voeren. Python biedt de mogelijkheid om nieuwe threads te maken en te beheren via de threading-module en de threading.Thread class.

Er kunnen situaties zijn waarin nieuwe threads worden beëindigd, normaal gesproken door de uitvoering ervan te voltooien of door een fout te genereren, en we ze opnieuw moeten starten. Dit kan verschillende redenen hebben, zoals:
• De thread voert een nuttige actie uit die we periodiek willen uitvoeren.
• De thread is een daemon-achtergrondtaak die we altijd willen uitvoeren.
• De thread voert een taak uit die vanaf een controlepunt opnieuw kan worden gestart.

Hoe je een draad opnieuw kunt starten
Python-threads kunnen niet opnieuw worden gestart of hergebruikt. Dit is waarschijnlijk een beperking van threads die door het onderliggende besturingssysteem worden geleverd.

Zodra een thread is beëindigd, kun je de methode start() er niet meer op aanroepen om deze opnieuw te gebruiken. Bedenk dat een thread om vele redenen kan eindigen, zoals het genereren van een fout of uitzondering, of wanneer de run()-functie is uitgevoerd.

Het aanroepen van de functie start() op een beëindigde thread resulteert in een RuntimeError die aangeeft dat threads slechts één keer kunnen worden gestart.

RuntimeError: threads can only be started once

Om een ​​thread in Python opnieuw te starten, moet je in plaats daarvan een nieuw exemplaar van de thread maken met dezelfde configuratie en vervolgens de functie start() aanroepen.

Nu we weten dat we een thread niet opnieuw kunnen starten, maar in plaats daarvan een nieuwe thread opnieuw moeten maken en starten, gaan we eens kijken naar enkele uitgewerkte voorbeelden.

Voorbeeld van het opnieuw starten van een beëindigde thread
We onderzoeken wat er gebeurt als we proberen een beëindigde thread in Python te starten. In dit voorbeeld zullen we een nieuwe thread maken om een functie uit te voeren, wachten tot de nieuwe thread is beëindigd en vervolgens proberen deze opnieuw te starten. We verwachten dat het mislukt met een RuntimeError.

Laten we eerst een functie definiëren die in een nieuwe thread moet worden uitgevoerd. De functie blokkeert eerst even en rapporteert vervolgens een bericht om ons te laten weten dat de nieuwe thread wordt uitgevoerd.

# doelfunctie
def taak():
    # blokkeer voor een moment
    sleep(1)
    # print een bericht
    print('Hallo van de nieuwe thread')

Vervolgens zal de hoofdthread een instantie van de klasse threading.Thread maken en deze configureren om onze aangepaste taak()-functie uit te voeren via het trefwoord ” target “.

# maak een nieuwe thread
thread = Thread(target=taak)

Vervolgens beginnen we met het uitvoeren van de thread die intern de run()-functie zal uitvoeren en op zijn beurt onze aangepaste taak()-functie zal aanroepen.

...
# start de thread
thread.start()

Vervolgens voegt de hoofdthread zich bij de nieuwe thread, die zal blokkeren (niet terugkeren) totdat de nieuwe thread is beëindigd.

...
# wacht op de thread dat deze eindigt
thread.join()

Ten slotte zal de hoofdthread proberen de beëindigde thread opnieuw te starten.

...
# Probeer en start de thread opnieuw
thread.start()

Als we dit samenvoegen, staat het volledige voorbeeld hieronder vermeld.

# voorbeeld voor hergebruik van de thread
from time import sleep
from threading import Thread
 
# doelfunctie
def taak():
    # blokkeer voor een moment
    sleep(1)
    # print een bericht
    print('Hallo van de nieuwe thread')
# maak een nieuwe thread
thread = Thread(target=taak)
# start de thread
thread.start()
# wacht op de thread dat deze eindigt
thread.join()
# probeer en start de thread opnieuw
thread.start()

Als je het voorbeeld uitvoert, wordt eerst een threadinstantie gemaakt en vervolgens de uitvoering ervan gestart. De nieuwe thread wordt gestart, blokkeert even en meldt dan een bericht.

De hoofdthread voegt zich bij de nieuwe thread en wacht tot deze wordt beëindigd. Eenmaal beëindigd, probeert de hoofdthread dezelfde thread opnieuw te starten. Het resultaat is een RuntimeError, zoals we hadden verwacht.

Hallo van de nieuwe thread
Traceback (most recent call last):
...
    raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

Dit benadrukt dat we de methode start() (bijvoorbeeld restart) inderdaad niet een thread kunnen noemen die al is beëindigd. Laten we vervolgens eens kijken naar een alternatieve aanpak voor het maken van een nieuwe threadinstantie.

Voorbeeld van het opnieuw starten van een thread met een nieuw exemplaar
We kunnen het herstarten van een thread simuleren door een nieuwe thread met dezelfde configuratie te maken en deze in plaats daarvan te starten. Er kan een nieuwe thread met dezelfde configuratie worden gemaakt. Dit omvat argumenten voor de constructor, zoals:

• Onderwerpnaam.
• Doelfunctie.
• Doelfunctieargumenten (tuple of dict).
• Daemon of niet.

Als we de code voor de class threading.Thread bekijken, kunnen we zien dat argumenten intern in de thread worden opgeslagen, hoewel ze privé zijn met namen als _name , _target , _args , enzovoort.
In plaats van te proberen toegang te krijgen tot deze eigenschappen, kunnen we in plaats daarvan gewoon een nieuwe threadinstantie maken en de argumenten handmatig aan de constructor opgeven.

...
# maak een nieuwe thread met dezelfde configuratie
thread2 = Thread(target=taak)

Start het dan en doe mee zoals voorheen.

...
# start de nieuwe thread
thread2.start()
# wacht op de nieuwe thread dat deze eindigt
thread2.join()

Aangezien we handmatig een nieuwe threadinstantie moeten configureren, kan het zinvol zijn om een ​​methode te gebruiken die een nieuwe threadinstantie retourneert met de voorkeursconfiguratie in die gevallen waarin een thread mogelijk opnieuw moet worden opgestart.

Bijvoorbeeld:

# functie voor het maken van threads 
def create_thread()
	return Thread(target=taak)

We zullen in dit geval geen functie gebruiken omdat onze thread een eenvoudige configuratie heeft. Als we dit samenvoegen, wordt hieronder het volledige voorbeeld weergegeven van het simuleren van het opnieuw opstarten van een thread met een nieuw exemplaar.

# voorbeeld van hergebruik van een thread
from time import sleep
from threading import Thread
 
# functie
def taak():
    # blokkeer voor een moment
    sleep(1)
    # print een bericht
    print('Hallo van de nieuwe thread')
 
# maak een nieuwe thread
thread = Thread(target=taak)
# start de thread
thread.start()
# wacht op de thread dat deze eindigt
thread.join()
# maak een nieuwe thread met dezelfde configuratie
thread2 = Thread(target=taak)
# start de nieuwe thread
thread2.start()
# wacht op de nieuwe thread dat deze eindigt
thread2.join()

Als je het voorbeeld uitvoert, wordt eerst de thread gemaakt en uitgevoerd zoals voorheen. De hoofdthread voegt zich bij de nieuwe thread totdat deze eindigt. De hoofdthread maakt vervolgens een nieuwe threadinstantie met dezelfde configuratie, start deze en sluit zich eraan aan. Zoals we verwachten, wordt deze nieuwe thread zonder incidenten uitgevoerd.

Hallo van de nieuwe thread
Hallo van de nieuwe thread

Have A Nice Day!

Geef als eerste een reactie

Laat een reactie achter

Het e-mailadres wordt niet gepubliceerd.


*