2010-11-19 45 views
1

J'essaye d'exécuter un thread de façon continue et de ne pas le faire bloquer par la boucle d'événement principal de tcl. Voici un exemple simple de ce que je suis en train de faire:Empêche le thread tcl d'être bloqué par la boucle d'événement principal

#!/bin/sh 
#\ 
exec tclsh "$0" "[email protected]" 

package require Thread 

set ::a_thread [thread::create {thread::wait}] 

proc start_a {} { 
    thread::send $::a_thread { 
    puts "Running a thread" 
    } 
    after 1000 a_start 
} 

proc infinite_loop {} { 
    while {1} { 
    puts "Loop" 
    after 500 
    } 
} 

start_a 
infinite_loop 

vwait forever 

Dans ce code, le infinite_loop proc est appelée et la boucle d'événement fonctionne à l'infini. Je voudrais si le a_thread pourrait encore fonctionner en arrière-plan si. Comment puis-je atteindre cet objectif?

Répondre

6

La boucle d'événement principal ne bloque pas votre thread. Au lieu de cela, vous utilisez la boucle d'événements principale pour créer des scripts à exécuter dans le thread. Au lieu de cela, exécutez le planificateur dans le fil lui-même:

code testé et fonctionne comme prévu:

thread::send $::a_thread { 
    proc loop {} { 
     puts "running a thread" 
     after 1000 loop 
    } 
    loop 
} 

while 1 { 
    puts "loop" 
    after 500 
} 
+0

Merci, les exemples du wiki de Tcl semblaient négliger ce type de situation. – elmt

5

La réponse est, bien sûr, celle donnée par slebetman. Cependant, une façon de déboguer ce genre de chose (surtout dans les cas les plus complexes) est de préfixer les messages imprimés par chaque thread par le résultat de thread::id, et de de s'assurer que vous imprimez un message au de commencer de chaque fois autour de la boucle. Par exemple:

package require Thread 

set ::a_thread [thread::create {thread::wait}] 

proc start_a {} { 
    puts "[thread::id]: Dispatch to $::a_thread" 
    thread::send $::a_thread { 
    puts "[thread::id]: Running a thread" 
    } 
    after 1000 a_start 
} 

proc infinite_loop {} { 
    while {1} { 
    puts "[thread::id]: Loop" 
    after 500 
    } 
} 

start_a 
infinite_loop 
puts "[thread::id]: Start main event loop" 
vwait forever 

qui vous aurait dit que l'envoi se passait une fois que la course dans l'autre thread se passe de manière synchrone (thread::send attend que le script pour terminer l'exécution par défaut), et que la boucle infinie empêche le démarrage de la boucle d'événement principal (et donc le rééchelonnement de la répartition). Puisque vous ne saviez pas qui faisait quoi, bien sûr, il y avait confusion!

+0

Astuce très utile. C'est mon premier coup de fil au tcl threading, donc cela aidera dans mes futures entreprises. – elmt