QObject:无法为处于不同线程中的父级创建子级
QObject: Cannot create children for a parent that is in a different thread
编辑:
我试着做你们在评论中告诉我的…:
Citizen * c = new Citizen(this);
QThread thread;
c->moveToThread(&thread);
connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions()));
thread.start();
这会产生更多的错误:
QThread: Destroyed while thread is still running
ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file c:ndk_buildreposqt-desktopsrccorelibthreadqthread_win.cpp, line 542
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
QObject::killTimers: timers cannot be stopped from another thread
我对这个错误有问题。。。我已经被这个问题困扰了两天,无法找到解决方案。
标题:
class Citizen : public QThread
{
Q_OBJECT
QNetworkAccessManager * manager;
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
Citizen(QObject * parent);
void run();
};
实施:
Citizen::Citizen(QObject * parent)
{
manager = new QNetworkAccessManager;
connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
void Citizen::onReplyFinished(QNetworkReply* net_reply)
{
emit onFinished(net_reply);
}
void Citizen::run()
{
manager->get(QNetworkRequest(QUrl("http://google.com"));
QEventLoop eLoop;
connect(manager, SIGNAL( finished( QNetworkReply * ) ), &eLoop, SLOT(quit()));
eLoop.exec(QEventLoop::ExcludeUserInputEvents);
qDebug() << "loaded google!";
exec();
}
当manager->get((被执行时,我得到以下错误:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0xc996cf8), parent's thread is QThread(0xaba48d8), current thread is Citizen(0xca7ae08)
当执行eLoop.exec((时:
QObject::startTimer: timers cannot be started from another thread
我以以下方式启动此线程:
Citizen * c = new Citizen(this);
c->start();
为什么会发生这种情况?如何解决这个问题?
QObject: Cannot create children for a parent that is in a different thread.
之所以会出现这种情况,是因为您正在Citizen的构造函数中创建QNetworkAccessmanager,该构造函数在"原始"线程中被调用。当Citizen对象移动到新线程时,QNetworkAccessmanager仍然将其线程关联设置为原始线程,但在运行调用中,它将尝试在新线程中创建QNetworkReply对象(可能还有其他对象(。这就产生了上面的警告。
如果您在运行槽中创建管理器(或者在Citizen对象移动到新线程后的任何时候(,则不会发生这种情况。
但是,您仍然有一些问题。例如,Citizen类实际上不需要是QThread。它不必要地使它复杂化。对你的目的(afaict(来说,子类化一个QObject就足够了。只需制作一个普通插槽,并将其连接到QThread::started((信号。正如OrcunC所指出的,您需要确保QThread实例的作用域正确。
有关线程的更多信息:http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
示例:
QThread *thread = new QThread;
thread->start();
Citizen *worker = new Citizen;
worker->moveToThread(thread);
//startWorking can be equivalent of the run function
//in your current implementation and this is where you should
//create the QNetworkAccessManager
QMetaObject::invokeMethod(worker,"startWorking");
我将尝试回答为什么您会看到QThread:Destroyed which thread which threaderror。
如果你这样做
void mtMethod () {
Citizen * c = new Citizen(this);
QThread thread;
c->moveToThread(&thread);
connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions()));
thread.start();
}
当您退出函数时,线程对象将被销毁,但已启动的线程仍在运行!。Qt警告您应该停止线程或在更大的范围内创建线程对象。(即,将其作为类的成员函数(。类似这样的东西:
class myClass
{
virtual ~myClass ();
QThread mythread;
};
myClass::~myClass
{
mythread.stop ();
}
void myClass::mtMethod () {
Citizen * c = new Citizen(this);
c->moveToThread(&mythread);
connect(&mythread, SIGNAL(started()), c, SLOT(ProcessActions()));
mythread.start();
}
在调用run之前,我不相信新线程存在。因此构造函数与run((是不同的线程。如果将管理器对象的创建从构造函数转移到run((,会发生什么?我想这将修复第一个错误,如果不是计时器错误的话。
此外,我认为许多人仍在以你的方式构建线程,但你可能想看看这一点。
您需要考虑线程亲和性。这个错误消息并不是在撒谎或疯狂,而是在告诉你到底出了什么问题。
您的问题主要是由于试图将QThread子类化。尽管文档推荐使用QThread,但它并不是使用QThread。有关更多信息和链接,请参阅此问答。
我还没有发现startTimers错误,尽管它可能与第一个错误有关。在任何情况下,您都应该能够修复第一个错误。我在Qt中遇到过几次这个问题,我发现解决这个问题的"最佳"方法是创建一个initialize函数和cleanUp函数。类的所有成员都是在调用run之前初始化为NULL的指针。请注意,"最佳"是在引号中,因为肯定会有不同的意见,但它适用于大多数情况下我。
标题
class Citizen : public QThread {
Q_OBJECT
QNetworkAccessManager * manager;
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
Citizen(QObject * parent);
void run();
private:
void initialize();
void cleanUp();
};
实施
Citizen::Citizen(QObject * parent) :
manager(NULL) {
}
void Citizen::onReplyFinished(QNetworkReply* net_reply) {
emit onFinished(net_reply);
}
void Citizen::run() {
initialize();
manager->get(QNetworkRequest(QUrl("http://google.com"));
QEventLoop eLoop;
connect(manager, SIGNAL( finished( QNetworkReply * ) ),
&eLoop, SLOT(quit()));
eLoop.exec(QEventLoop::ExcludeUserInputEvents);
qDebug() << "loaded google!";
exec();
cleanUp();
}
void Citizen::initialize() {
manager = new QNetworkAccessManager;
connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
void Citizen::cleanUp() {
delete manager;
disconnect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- C++ 线程创建/删除与线程停止/恢复
- Qt - 如何从线程创建 QFuture
- 我可以使用Qt线程ID为每个线程创建唯一的缓存吗?
- 零MQ 后台线程创建
- OpenMP 线程创建
- GLFW & ImGui:从 main 以外的线程创建 ImGui 控件
- 对象:无法为位于不同线程中的父线程创建子级
- C++ 11:线程创建给我一个"Attempt to use a deleted function"错误
- C 的周期性线程创建
- MPI - 当数组初始化值必须为常量时,如何为工作线程创建部分数组
- 当主GUI线程被阻塞时,如何从工作线程创建无模式对话框
- 多个线程创建5个线程来计算质数
- 为线程创建模板
- 线程创建,CRT和DLL是如何完成的?
- 同步线程创建和销毁(静态)对象
- 竞争条件:一个线程创建静态对象,另一个线程在初始化完成之前使用它.如何处理
- 从不同线程创建QMainWindow
- QFuture 无法为位于不同线程中的父线程创建子级
- ( QNativeSocketEngine)QObject:无法为位于不同线程中的父线程创建子级