我已经使用Python的线程模块来运行子进程并等待它完成。 我使用以下行进行线程处理:
t1=Thread(target=self.routineFunction, args=(self, "file1.txt", "file2.txt", self.nextFunction)).start()
在我的函数routineFunction(self,file1,file2,nextFunction)中,我调用下一个函数,一旦子进程运行完毕就运行。
在此之前一切正常。
但是如果我在下一个函数中创建新的QObject项,我会收到很多错误: - “QPixmap:在GUI线程外使用pixmaps是不安全的” - “QObject :: startTimer:QTimer只能用于以QThread启动的线程”
我的猜测是,当我从例程调用nextFunction时,它在与例程相同的线程中运行,因此出现错误。 有没有办法从“主”或“正常”线程中的例程调用函数?。
感谢您的帮助。
答案 0 :(得分:2)
通常,可以从其他线程调用函数。但是许多GUI库(其中包括QT)对此行为有一些限制。
例如,有一个名为'GUI thread'的指定线程可以处理所有图形内容,例如从OS调度消息,重绘窗口等等。而且你还限制使用GUI来处理这个唯一的线程。因此,例如,您不应该在其他线程中创建QPixmap
。
QTimer
使用了一些QThread
的内部数据,所以你应该在只用QThread
开头的线程中使用这样的定时器,而不是用普通的Python thread
模块。
回到你的问题,如果你不想使用QT,你应该使用QThread
生成你的线程,并使用postEvent()
方法将事件发布到GUI线程。这将保证QT内部数据结构的一致性。
因此,您可以在任何QT线程中运行您的代码,但是如果您想使用GUI(QObject
使用QPixmap
,那么就是这种情况),您需要处理此类调用仅在GUI线程中。
答案 1 :(得分:0)
好的,所以我认为可以解决这个问题。不幸的是,我发现很难将我当前的脚本从Thread转换为QThread(我不熟悉一般的线程)。
我找到了一个解决方法: 我没有传递nextFunction作为参数,而是传递一个队列= Queue.Queue(),如果我的新线程中的子进程成功,我使用queue.put(True)。没有更多的nextFunction,我只是在queue.get()中等待队列中的值。 通过这样做,我可以继续在GUI线程中。