2016-06-07 30 views
5

Sto creando una semplice applicazione GUI usando PyQt5 dove richiedo alcuni dati da un'API che viene poi utilizzata per popolare vari controlli dell'interfaccia utente.Discussione singola per tutte le attività o più lavoratori specifici?

Gli esempi che stavo seguendo sui thread di lavoro in PyQt sembrano tutti sottoclasse QThread e quindi eseguono la loro logica aziendale nel metodo run() sottoposto a override. Funziona bene ma voglio eseguire diverse chiamate API in momenti diversi utilizzando un worker.

Quindi la mia domanda è: devo creare un thread di lavoro specifico per ogni operazione che desidero o esiste un modo per avere una classe thread singola che posso utilizzare per eseguire operazioni diverse in momenti diversi e quindi evitare l'overhead di creare sottoclassi di thread diverse?

+2

Non si dovrebbe creare una sottoclasse di 'QThread'. Invece, usa 'QtConcurrent :: run', o forse sottoclasse' QObject', e sposta questi oggetti worker in un singolo thread worker. –

risposta

6

Quello che puoi fare è progettare un oggetto per svolgere tutte queste attività (eredita QObject per slot/segnali). Diciamo che ogni attività è definita come una funzione separata - consente di designare queste funzioni come slot.

Poi (un ordine generale di eventi):

  • un'istanza di un oggetto QThread.
  • istanzia la tua classe.
  • Sposta l'oggetto nella discussione utilizzando YouClass->moveToThread(pThread).
  • Definire ora un segnale per ogni slot e collegare questi segnali agli slot pertinenti nel proprio oggetto.
  • gestita Infine il filo con pThread->start()

Ora è possibile emettere un segnale per fare un compito particolare nel thread. Non hai bisogno di sottoclasse QThread, usa solo una classe normale derivata da QObject (in modo da poter usare slot/segnali).

È possibile utilizzare una classe in una discussione per eseguire molte operazioni (nota: verranno accodate). Oppure creare molte classi in molti thread (per eseguire "parallel").

Non so python abbastanza bene per tentare un esempio qui quindi non lo farò: o

Nota: Il motivo per sottoclasse QThread sarebbe se si voleva estendere la funzionalità del Classe QThread - ad es. Aggiungere più/funzioni specifiche relative ai thread. QThread è una classe che controlla un thread e non è pensata per essere utilizzata per eseguire attività arbitrarie/generiche ... anche se è possibile utilizzare lo se lo si desidera :)

+0

Risposta eccellente, in particolare suggeriscono che i lavori verranno automaticamente messi in coda. Forse scriverò un esempio per questo. – Trilarion

+0

@Trilarion grazie, e sì, per favore, sentitevi liberi di aggiungere esempi:) –

3

Ecco un esempio conciso di uno (ma potrebbe essere quanti ne vuoi) oggetto lavoratore che viene spostato su un singolo QThread in esecuzione (avviato) e sta comunicando tramite segnali. Anche il filo viene fermato alla fine. Dimostra cosa code_fodder ha delineato in his answer.

from PyQt4 import QtCore 
QtCore.Signal = QtCore.pyqtSignal 

class Master(QtCore.QObject): 

    command = QtCore.Signal(str) 

    def __init__(self): 
     super().__init__() 

class Worker(QtCore.QObject): 

    def __init__(self): 
     super().__init__() 

    def do_something(self, text): 
     print('current thread id = {}, message to worker = {}'.format(int(QtCore.QThread.currentThreadId()), text)) 

if __name__ == '__main__': 

    app = QtCore.QCoreApplication([]) 

    # give us a thread and start it 
    thread = QtCore.QThread() 
    thread.start() 

    # create a worker and move it to our extra thread 
    worker = Worker() 
    worker.moveToThread(thread) 

    # create a master object and connect it to the worker 
    master = Master() 
    master.command.connect(worker.do_something) 

    # call a method of the worker directly (will be executed in the actual thread) 
    worker.do_something('wrong way to communicate with worker') 

    # communicate via signals, will execute the method now in the extra thread 
    master.command.emit('right way to communicate with worker') 

    # start the application and kill it after 1 second 
    QtCore.QTimer.singleShot(1000, app.quit) 
    app.exec_() 

    # don't forget to terminate the extra thread 
    thread.quit() 
    thread.wait(5000)