Многопоточное приложение Python зависает во время работы своих потоков - PullRequest
3 голосов
/ 05 января 2010

Я пытаюсь создать MainObject, который доступен как служба DBus. Этот MainObject всегда должен реагировать на другие объекты / процессы и на эту неблокировку даже при обработке своих элементов. по этой причине элементы обрабатываются в отдельном потоке один за другим (в стиле очереди). Вы можете добавлять элементы в MainObject через DBus или CommandLine. Я упростил пример (без dbus, без командной строки), чтобы показать мою проблему.

Моя проблема в том, что если я снова включаю tt.join (), приложение работает, как и ожидалось, но блокируется для других процессов. Неудивительно, что tt.join заставляет приложение ждать, пока отдельный поток завершит свою работу. С другой стороны, если tt.join () остается отключенным, приложение не блокирует внешние события dbus, но никогда не доходит до «ThreadTest done!» (посмотрите на реальный результат)

Что я хочу, так это мой ожидаемый результат, но приложения должны оставаться отзывчивыми.

#!/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()

ожидаемый результат:

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!

реальная продукция:

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 ...

Ответы [ 2 ]

2 голосов
/ 05 января 2010

По умолчанию привязки объектов не поддерживают многопоточность. Пожалуйста, попробуйте сделать следующее сразу после импорта gobject:

gobject.threads_init()
0 голосов
/ 05 января 2010

Потоки в python могут быть ловушкой - на самом деле это открытая проблема. Основная проблема - GIL - глобальная блокировка интерпретатора Python.

Одним из способов, которые они изобрели для преодоления этого, является модуль «многопроцессорности» (впервые в Python 2.6) - он сохраняет интерфейс «многопоточности», но фактически выполняет код в отдельном процессе: Вы можете попробовать jsut заменить htreading на многопроцессорность - но: выполнять все взаимодействия с dbus, GUI и т. Д. В главном «потоке» (то есть в одном процессе) и обмениваться данными с подпроцессами (строками, списками словари и т. д.) ... это будет работать нормально.

Кроме того, я не могу понять, почему все это регулярное выражение Voodo просто проверить, присутствует ли данная строка в возвращаемом значении threading.enumerate ?? В Python есть даже оператор «in» (поэтому вам даже не нужно использовать индекс str или искать методы):

Вы можете заменить весь этот check_running метод на:

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