Multithreading 线程化:PyQt崩溃,带“0”;“退出队列时队列中存在未知请求”;

Multithreading 线程化:PyQt崩溃,带“0”;“退出队列时队列中存在未知请求”;,multithreading,python-2.7,pyqt4,Multithreading,Python 2.7,Pyqt4,我正在开发的应用程序的一部分需要向一小群人发送一些电子邮件。由于连接到SMTP服务器并发送电子邮件可能需要一些时间,因此我希望在此操作期间使用后台线程提供一个进度条来完成此工作 现在的情况是,我可以实现一个工作正常的测试结构,但一旦我尝试从应用程序的后端创建一个对象来实际执行任何电子邮件操作,它就会完全崩溃(好像它发生了故障),并将其转储到控制台: [xcb] Unknown request in queue while dequeuing [xcb] Most likely this is a

我正在开发的应用程序的一部分需要向一小群人发送一些电子邮件。由于连接到SMTP服务器并发送电子邮件可能需要一些时间,因此我希望在此操作期间使用后台线程提供一个进度条来完成此工作

现在的情况是,我可以实现一个工作正常的测试结构,但一旦我尝试从应用程序的后端创建一个对象来实际执行任何电子邮件操作,它就会完全崩溃(好像它发生了故障),并将其转储到控制台:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted
我在搜索这些错误时发现的唯一相关线程表明信号实现错误(对于PySide,),但在我的例子中,信号工作完全正常,直到我尝试创建该对象(它根本不基于Qt类)

以下是我的GUI代码的简化版本:

class SendingDialog(QtGui.QDialog):
    def __init__(self, parent, optsDict, cls, zid):
        QtGui.QDialog.__init__(self)
        self.form = Ui_Dialog()
        self.form.setupUi(self)
        # initialize some class variables...

        self.beginConnect()
        self.thread = WorkerThread()
        self.thread.insertOptions(self.opts, self.cls, self.zid)
        self.thread.finished.connect(self.endOfThread)
        self.thread.serverContacted.connect(self.startProgress)
        self.thread.aboutToEmail.connect(self.updateProgress)
        self.thread.start()

    def beginConnect(self):
        # start busy indicator

    def startProgress(self):
        # set up progress bar

    def updateProgress(self):
        # increment progress bar

    def endOfThread(self):
        self.thread.quit()
        self.reject()

class WorkerThread(QtCore.QThread):
    serverContacted = QtCore.pyqtSignal(name="serverContacted")
    aboutToEmail = QtCore.pyqtSignal(name="aboutToEmail")

    def insertOptions(self, opts, cls, zid):
        self.opts = opts
        self.cls = cls
        self.zid = zid

    def run(self):
        # upon running the following line, the application crashes.
        emailman = db.emailing.EmailManager(self.opts, self.cls, self.zid)
如果我在
run();但是,当我尝试实例化
EmailManager
时,整个过程就崩溃了

EmailManager
是从
object
派生的一个不起眼的类,采用我给它的参数(
opts
是一个字典,
cls
是一个不同类型的类似不起眼的对象,
zid
只是一个普通数字)。构造函数如下所示:

def __init__(self, optsDict, cls, zid):
    self.opts = optsDict
    self.cls = cls
    self.historyItem = HistoryItem(zid)
    self.studentsList = studentsInClass(cls)
    self.connection = None
我正在基于这些参数构建一些其他对象,但除此之外,没有发生任何复杂或异常的事情。
db.email
模块中的代码根本不使用Qt或线程

我甚至不知道如何开始调试这个,所以任何关于可能发生的事情或我如何尝试找出答案的建议都将非常感谢

编辑:如果有用的话,这里是来自gdb的回溯(我不知道发生了什么事情,所以觉得它有用):

哇,这太晦涩了

X11窗口函数显然不是线程安全的,除非显式设置为线程安全,并且出于任何原因PyQt不会自动将其设置为线程安全。这可以通过在QApplication构造函数之前添加以下内容来纠正:

QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)

请参阅上的文档。

如果创建一个简单的测试应用程序并尝试在Python线程中使用
EmailManager
(使用
threading
模块),会发生什么情况?
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)