从辅助线程调用主线程函数

Posted

技术标签:

【中文标题】从辅助线程调用主线程函数【英文标题】:call function of main thread from secondary thread 【发布时间】:2014-12-23 15:19:42 【问题描述】:

我正在 PyQt 中制作一个 GUI,供用户创建海量数据的备份。

GUI(主线程)正在接受用户的输入。 rsync 命令(用于备份)也在主线程中被调用,因此窗口被冻结。

目的是尝试 qthread 以使应用程序在不冻结的情况下运行。

我的搜索资料:

1:https://www.youtube.com/watch?v=o81Q3oyz6rg。该视频展示了如何通过在辅助线程中运行其他任务来不冻结 GUI。我已经尝试过了,它有效。但它无助于在工作线程中运行命令。

尽管在辅助线程中调用了 rsync,但 gui 仍然冻结。我做错了什么?。

import sys
from PyQt4 import QtCore, QtGui
from backUpUi import Ui_MainWindow
import threading, Queue

class callerThread(QtCore.QThread):

    def __init__(self, func, parent=None, *args, **kwargs):
        super(callerThread, self).__init__(parent)
        self._func = func
        self._args = args
        self._kwargs = kwargs

    def run(self):
        self._func(*self._args, **self._kwargs)


class Monitor(QtCore.QObject):

    updateText = QtCore.pyqtSignal(str)

    def update_list(self):
        t_monitor = callerThread(self.monitor_vector, parent=self)
        t_monitor.daemon = True
        t_monitor.start()

    def monitor_vector(self):
        self.updateText.emit('updated list')


class backUpMain(QtGui.QMainWindow):

    def __init__(self,parent=None):
        super(backUpMain, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.connect(self.ui.okButton, QtCore.SIGNAL("clicked()"), self.startThread)
        self.ui.cancelButton.released.connect(sys.exit)
        self.monitor = Monitor()


    def _handlebackUpdate(self, txt):
        QtGui.QMessageBox.information(self, "thread started!", txt)
        self.ui.logEdit.clear()
        self.ui.logEdit.setText(txt)


    def startThread(self):

        self.monitor = Monitor()
        self.monitor.updateText.connect(self._handlebackUpdate)
        self.monitor.update_list()


    def threadDone(self,text1):
        self.ui.logEdit.append("Worker Thread finished processing %s" % text1)



    def exitWindow(self):
        self.ui.close()


def main():
    app = QtGui.QApplication(sys.argv)
    dialog = backUpMain()
    dialog.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

【问题讨论】:

任何有线索的人。我也有类似的问题 【参考方案1】:

在寻找答案时,qtcentre 提供了帮助。

    您需要有单独的信号类
class MySignal(QtCore.QObject):
    sig = QtCore.pyqtSignal(list)
    sigStr = QtCore.pyqtSignal(str)

此信号用于线程之间的通信。

    从主线程到工作线程通信,

    在定义 Ui 的类的 init 中创建 qthread 实例 在 init 或需要的地方从主线程传递参数。

class MyThread(QtCore.QThread):

  def __init__(self, parent = None, *args, **kw):             .           .
      self.setData(*args, **kw)


  def setData(self, userShotList, inData, outData, dept):
      self.userShotList = userShotList            .           .

这种方式数据从 main 传递到 worker。

    从工作线程到主线程通信

类MyThread(QtCore.QThread):

  def __init__(self, parent = None, *args, **kw):             .           .           .           .
      self.signal = MySignal()

需要执行不同类型的信号 (list, str ...) 在 MySignal() 中定义

def xyz(self): self.signal.sigStr.emit(message)

希望这会有所帮助。

【讨论】:

我接受了你的部分答案,但为了我的目的,让它更清楚一点 - 如何将信号从一个线程发送到另一个线程:***.com/a/48999586/2441026

以上是关于从辅助线程调用主线程函数的主要内容,如果未能解决你的问题,请参考以下文章

在辅助线程中调用 select()/pselect() 会导致主线程阻塞吗?

如何从主线程超时java线程?

通过 Unity 中的后台线程调用主线程中的函数

与主线程相比,在辅助线程上崩溃是不是有优势?

从睡眠中唤醒主线程

子线程怎么不阻塞主线程