2010-01-05 11 views
3

J'essaie de créer un MainObject disponible en tant que service DBus. Ce MainObject doit toujours rester sensible aux autres objets/processus et pour ce non-blocage même lors du traitement de ses éléments. pour cette raison, les éléments sont traités les uns après les autres dans un fil séparé (style de file d'attente). Vous pouvez ajouter des éléments à MainObject via DBus ou CommandLine. J'ai simplifié l'échantillon (pas de dbus, pas de ligne de commande) pour montrer mon problème.L'application python multithread se bloque lors de l'exécution de ses threads

Mon problème est, que si je réactive 'tt.join()' l'application fonctionne comme prévu, mais elle bloque les autres processus. Pas étonnant, tt.join fait attendre l'application jusqu'à ce que le thread séparé a terminé son travail. D'un autre côté, si 'tt.join()' reste désactivé, l'application ne bloque pas les événements dbus externes, mais n'arrive jamais à 'ThreadTest done!' (regardez la sortie réelle)

Ce que je veux, c'est ma sortie attendue mais les applications devraient rester réactives.

#!/usr/bin/python2.5 

import gobject 
import threading 
import re 
import time 

class ThreadTest(threading.Thread): 

    def __init__(self): 
    threading.Thread.__init__ (self)  
    print ' ThreadTest created!' 

    def run(self): 
    print ' ThreadTest running ...' 
    time.sleep(1) 
    print ' ThreadTest done!' 
    return True 

class MainObject(): 
    def __init__(self): 
    self.timer = gobject.timeout_add(1000, self.update) 
    self.loop = gobject.MainLoop() 
    print 'MainObject created!' 

    def update(self): 
    print 'MainObject updating ...' 
    if self.check_running() == False: 
     tt = ThreadTest() 
     tt.start() 
     #tt.join() 
    return True 

    def check_running(self): 
    running = False 
    expr = re.compile('ThreadTest') 
    for threadstr in threading.enumerate(): 
     matches = expr.findall(str(threadstr)) 
     if matches: 
     running = True 
    return running 


mo = MainObject() 
mo.loop.run() 

résultat attendu:

MainObject created! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
    ThreadTest done! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
    ThreadTest done! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
    ThreadTest done! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
    ThreadTest done! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
    ThreadTest done! 

production réelle:

MainObject created! 
MainObject updating ... 
    ThreadTest created! 
    ThreadTest running ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
MainObject updating ... 
+0

Dupliate: http://stackoverflow.com/questions/1796588/python-thread-and-gobject – ebo

Répondre

2

Le gobject Les liaisons par défaut ne sont pas multithread-aware. S'il vous plaît essayer de faire ce qui suit juste après avoir importé gobject:

gobject.threads_init() 
+0

fonctionne très bien! Merci! bon sang ... je passe 2 jours pour moi en cherchant ceci: D –

+0

tu m'as sauvé de pleurer :) –

0

Threads en python peut être un piège - il est un problème ouvert, en fait. Le principal problème est le GIL - Global Interpreter Lock de Python. L'un des moyens qu'ils ont inventé pour surmonter cela est le module "multiprocessing" (nouveau dans python 2.6) - il préserve l'interface "threading", mais exécute en fait le code dans un processus séparé: Vous pouvez essayer de remplacer jsut htreading par multiprocessing - mais: faire toutes les interactions dbus, GUI, etc. sur un "thread" principal - (ie un seul processus) - et échanger des données avec les sous-processus (chaînes, listes, dictionnaires, etc.). .. cela fonctionnerait bien.

Aussi, je ne peux pas comprendre pourquoi tout ceci regexp Voodo juste pour vérifier si une chaîne donnée est présente sur la valeur de retour de threading.enumerate ?? Python a même le « dans » l'opérateur (vous ne disposez même de ne pas utiliser l'index de la str, ou trouver des méthodes):

vous pouvez remplacer méthode check_running entier pour:

def check_running(self): 
    return 'ThreadTest' in str(threading.enumerate()) 
+0

merci aussi. informations de fond intéressantes, toujours bon à savoir! –