2012-05-14 2 views
0

Я следующий код:Параллельное выполнение QThread или QRunnable объектов в Python

from PySide.QtCore import * 
import time 

class GUI(object): 

    IDLIST = [i for i in xrange(20)] 
    UNUSEDIDS = [i for i in xrange(20)] 

    def __init__(self): 
     print "GUI CLASS INITIALIZED!" 

     worker = Worker() 
     worker2 = Worker2() 

     threadpool = QThreadPool() 
     threadpool.setMaxThreadCount(10) 

     for i in xrange(5): 
      #Alternate between the two 
      #threadpool.start(worker) 
      #worker2.start() 


    @classmethod 
    def delegator(self): 
     """Irrelevant to the question, I need this method for something else""" 
     USEDIDS = [] 

     toUse = self.UNUSEDIDS[0] 
     USEDIDS.append(toUse) 
     self.UNUSEDIDS.pop(0) 

     return toUse 


class Worker(QRunnable): 

    def __init__(self, parent=None): 
     super(Worker, self).__init__(parent) 

    def run(self): 
     #idInUse = getattr(GUI, "delegator") 
     idInUse = GUI.delegator() 
     print "Hello world from QRunnable", idInUse 
     #time.sleep(5) 

class Worker2(QThread): 

    def __init__(self, parent=None): 
     super(Worker2, self).__init__(parent) 

    def run(self): 
     idInUse = GUI.delegator() 
     print "Hello world from QThread", idInUse  


s = time.time() 
GUI() 
print "Done in %s" % ((time.time()-s) * 1000) 

Я думаю, что желаемый эффект очевиден из кода. Я хочу показать «Hello world from QThread/QRunnable». Поскольку я пишу многопоточное приложение, в моей части GUI __init__ у меня есть цикл, который запускает параллельные потоки.

Дело в том, что с помощью QRunnable это работает отлично. Все указанные мной 5 потоков выполняются одновременно, одновременно. Однако с QThread это не так. Вместо этого возникает следующая ошибка:

QThread: Destroyed while thread is still running

И не выполняется вообще.

Обычно я бы совсем не виду, используя QRunnable, однако, он не является производным от QObject (так что не может непосредственно излучать сигналы, хотя можно построить QObject() внутри него), а также она не имеет метод .stop() которые мне очень нужны. Googling показал, что нет возможности остановить выполнение QRunnable? С другой стороны, у QThread есть оба метода, которые мне нужны.

Итак, я думаю, что мой вопрос заключается в том, как сделать несколько одинаковых QThreads одновременно, или как прекратить выполнение QRunnable?

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

ответ

0

QThread: Destroyed while thread is still running -exception происходит потому, что вы никогда не ждать, пока ваши темы, чтобы закончить, и вы не будете держать любое . ссылки на них (ни к worker, worker2 или threadpool, поэтому когда ваши __init__ заканчивает он разрушается

если вы сохранить ссылку на этом объекты, то это должно работать:

def __init__(self): 
    print "GUI CLASS INITIALIZED!" 

    self.worker = Worker() 
    self.worker2 = Worker2() 

    self.threadpool = QThreadPool() 
    self.threadpool.setMaxThreadCount(10) 

    for i in xrange(5): 
     #Alternate between the two 
     self.threadpool.start(worker) 
     # this is wrong, by the way! 
     # you should create 5 workers, not call start 5 times... 
     self.worker2.start() 

и при вызове методов wait/waitForDone в потоке/пуле еще лучше.
Для QThreadPool это неявно происходит when it's (C++) destructor is called. Если бы это было не так, то ваша программа не работала бы с QRunnable s в первую очередь eiter. Для QThreadnothing like this happens и даже упоминается, что это, вероятно, приведет к сбою. Так что лучше явно ждать нити, чтобы закончить ...

также, я надеюсь, что вы уже знаете this

+0

код вы предоставили действительно работает - это именно тот, который я intially использовал. Даже когда я сохраняю ссылки на объекты, такая же ошибка все равно происходит. Вызвав деструктор 'QThreadPool()', я убью все 'QRunnable()' внутри него - и это то, чего я не хочу. Если я дождался окончания потока до начала нового потока, то нет реальной точки, потому что я хочу, чтобы выполнялось параллельное выполнение, а не один поток за другим. Я также не называл деструктор 'QThread()', но скорее назвал бы его метод '.terminate()', который отлично работает. –

+0

вам не нужно ждать завершения старого потока, прежде чем начинать новый. вы можете создать, например, 5 или 10 экземпляров в цикле и поместить их в список, чтобы сохранить ссылки. И вы не можете вызывать деструктор C++ из python, что происходит неявно, когда переменная выходит за пределы области и собирается мусор.вы можете удалить объекты python, которые приведут к тому же (и авария, вероятно, приведет к сбою программы для запуска QThread). – mata

+0

Да, как я уже сказал, я попытался создать экземпляры внутри цикла, но безрезультатно. –

Смежные вопросы