如何防止PyQt对象在不同线程中被垃圾回收?

5 投票
2 回答
2230 浏览
提问于 2025-04-16 05:46

我正在使用Qt 4.7和PyQt 4.7来构建一个多线程的图形界面程序。我一直小心翼翼地管理PyQt对象,确保它们只在一个用户界面线程中运行,这样可以避免同步问题,整体上没有什么问题。

但是,有时候,当其他线程启动Python的垃圾回收器时,Qt对象的析构函数会被立即调用,这样就会导致Qt内部的一个检查失败。

我可以在调试版本中定义QT_NO_DEBUG,这样应该没问题,因为被回收的对象几乎不会引起同步问题。但我还是觉得关闭其他调试信息并不是个好主意。我该如何防止这种情况发生呢?

#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD)
void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
{
    QThread *currentThread = QThread::currentThread();
    QThread *thr = receiver->thread();
    Q_ASSERT_X(currentThread == thr || !thr,
               "QCoreApplication::sendEvent",
               QString::fromLatin1("Cannot send events to objects owned by a different thread. "
                                   "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
               .arg(QString::number((quintptr) currentThread, 16))
               .arg(receiver->objectName())
               .arg(QLatin1String(receiver->metaObject()->className()))
               .arg(QString::number((quintptr) thr, 16))
               .toLocal8Bit().data());
    Q_UNUSED(currentThread);
    Q_UNUSED(thr);
}
#elif defined(Q_OS_SYMBIAN) && defined (QT_NO_DEBUG) 

2 个回答

1

我建议你使用pyqtSignal。你可以为你的线程创建信号,当它们的任务完成时,就可以发送这些信号,而接收信号的部分就是你连接的函数。

6

这个问题出现在PyQt的邮件列表中,讨论的主题是

"PyQt和Python垃圾回收器结合时的微妙错误"
http://www.riverbankcomputing.com/pipermail/pyqt/2011-August/030376.html

Kovid Goyal在这里提出了一种解决方法
http://www.riverbankcomputing.com/pipermail/pyqt/2011-August/030378.html

他写道:

作为我项目中的一种解决方法, 我禁用了自动垃圾回收器,并通过QTimer在GUI线程中手动运行垃圾回收。

他在那儿还提供了一个代码示例。

撰写回答