PyQt从非QThread唤醒主线程

时间:2016-10-05 09:42:39

标签: python multithreading qt pyqt qthread

我有一个PyQt应用程序,它通过回调从外部源接收信息,这些回调是从不受我控制且不是QThread的线程调用的。在没有轮询的情况下,将这些信息传递给主线程的正确方法是什么?特别是,我想发出一个Qt信号,这样我就可以在新数据到达时唤醒主线程(或另一个QThread)。

2 个答案:

答案 0 :(得分:1)

信号的默认连接类型为Qt.AutoConnection,文档描述如下:

  

如果信号是从与接收不同的线程发出的   对象,信号排队,表现为Qt :: QueuedConnection。   否则,直接调用插槽,表现为   Qt的:: DirectConnection。连接类型是在确定时确定的   发出信号。

因此,在发出信号之前,Qt只需比较发送方和接收方的当前线程关联性,然后再决定是否对其进行排队。 如何最初启动底层线程无关紧要。

这是一个使用python工作线程的简单演示:

$ python test.py
show: [MainThread]
start: [MainThread]
work: [Worker]
callback: 0 [Worker]
received: 0 [MainThread]
still active...
callback: 1 [Worker]
received: 1 [MainThread]
still active...
callback: 2 [Worker]
received: 2 [MainThread]
still active...
callback: 3 [Worker]
received: 3 [MainThread]
callback: 4 [Worker]
received: 4 [MainThread]

典型输出:

-- Sample data
-- including an id for use as a tie-breaker for a unique pk/clustered index on c1 & c2
DECLARE @tbl TABLE 
  (id int identity not null, c1 char(1), c2 tinyint, primary key (c1,c2,id));
INSERT @tbl VALUES ('a', 2), ('b', 1), ('a', 1), ('b', 3), ('a', 2);

-- Solution
SELECT c1, MaxOccurs = MAX(c)
FROM
(
  SELECT c1, c2, c = COUNT(1)
  FROM @tbl
  GROUP BY c1, c2
) x
GROUP BY c1;

答案 1 :(得分:0)

如果您只是轮询外部设备或库,我会像处理它一样处理它。创建一个处理回调的单独工作线程,并向主GUI线程发出信号。

class Worker(QObject):

    data_ready = pyqtSignal(object, object)

    def callback(self, *args, **kwargs):
        self.data_ready.emit(args, kwargs)


class Window(...)

    def __init__(self):
        ...
        self.worker = Worker(self)
        # Connect worker callback function to your external library
        library.register_callback(self.worker.callback) #??
        ...

        # Mover worker to thread and connect signal
        self.thread = QThread(self)
        self.worker.data_ready.connect(self.handle_data)
        self.worker.moveToThread(self.thread)
        self.thread.start()

    @pyqtSlot(object, object)
    def handle_data(self, args, kwargs):
        # do something with data