QObject:无法为位于不同线程中的父级创建子级
编辑:
我尝试做你们在评论中告诉我的事情...:
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_buildrepos\qt-desktop\src\corelib\thread\qthread_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();
为什么会发生这种情况?怎么解决这个问题呢?
EDIT:
I tried doing what you guys told me in comments ... :
Citizen * c = new Citizen(this);
QThread thread;
c->moveToThread(&thread);
connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions()));
thread.start();
This produces even more errors:
QThread: Destroyed while thread is still running
ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file c:\ndk_buildrepos\qt-desktop\src\corelib\thread\qthread_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
I am having problems with this error ... I'm stuck on this for 2 days already and can't get a solution.
Header:
class Citizen : public QThread
{
Q_OBJECT
QNetworkAccessManager * manager;
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
Citizen(QObject * parent);
void run();
};
Implementation:
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();
}
When manager->get() gets executed, I get the following error:
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)
When eLoop.exec() gets executed:
QObject::startTimer: timers cannot be started from another thread
I start this thread in the following manner:
Citizen * c = new Citizen(this);
c->start();
Why does this happen? How to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您得到这个是因为您正在 Citizen 的构造函数中创建 QNetworkAccessmanager,该构造函数在“原始”线程中被调用。当 Citizen 对象移动到新线程时,QNetworkAccessmanager 仍然将其线程关联设置为原始线程,但在运行调用中它将尝试在新线程中创建 QNetworkReply 对象(可能还有其他对象)。这会产生上面的警告。
如果您在运行槽中(或在 Citizen 对象移动到新线程后的任何时候)创建管理器,则不会发生这种情况。
但是您仍然有一些问题。例如,Citizen 类实际上不需要是 QThread。它不必要地使事情复杂化。对 QObject 进行子类化就足以满足您的目的(afaict)。只需创建一个普通插槽并将其连接到 QThread::started() 信号即可。正如 OrcunC 指出的,您需要确保 QThread 实例的作用域正确。
有关线程的更多信息:http://blog. qt.io/blog/2010/06/17/youre-doing-it-wrong/
示例:
You get this because you are creating the QNetworkAccessmanager in the constructor of Citizen, which is being called in the "original" thread. When the Citizen object is moved to the new thread the QNetworkAccessmanager still has its thread affinity set to the original thread but in the run call it will attempt to create the QNetworkReply object ( and probably other objects aswell ) in the new thread. Which produces the warning above.
If you create the manager in the run slot(or at any point after the Citizen object is moved to the new thread) that will not happen.
However you still have some issues. For instance, the Citizen class really doesn't need to be a QThread. It needlessly complicates it. It will suffice for your purpose(afaict) to subclass a QObject. Just make a normal slot and connect that to the QThread::started() signal. And as OrcunC pointed out you need to make sure that the QThread instance is properly scoped.
For more on threading: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
Example:
我将尝试回答为什么您会看到 QThread: Destroyed while thread is still running 错误。
如果这样做
退出函数时线程对象将被销毁,但已经启动的线程仍在运行!。 Qt 警告您应该停止线程或在更大的范围内创建线程对象。 (即使其成为您班级的成员函数)。像这样的东西:
I will just try to answer why you are seeing QThread: Destroyed while thread is still running error.
If you do this
The thread object will be destroyed when you exit the function but the thread that has been started is still running !. Qt is warning you that you should either stop the thread or create the thread object in a bigger scope. (i.e make it a member function of your class). Something like this :
在调用 run 之前,我不相信新线程存在。所以构造函数是与 run() 不同的线程。如果将管理器对象的创建从构造函数移至 run() 会发生什么?我想这将修复第一个错误,如果不是计时器错误的话。
另外,我认为很多人仍在按照您的方式构建线程,但您可能想查看 这个。
I don't believe the new thread exists until run is called. So the constructor is a different thread than run(). What happens if you move the creation of the manager object from the constructor to run()? I imagine that will fix the first error, if not the timer error as well.
Also, I think many people are still building threads the way you are, but you might want to check out this.
您需要考虑线程亲和性。该错误消息并不是说谎或疯狂,而是准确地告诉您出了什么问题。
You need to consider thread affinity. That error message is not lying or insane, it's telling you exactly what's wrong.
您的问题主要是由于尝试子类化 QThread 造成的。尽管文档推荐这样做,但这并不是使用 QThread 的最佳方法。请参阅此问题和答案获取更多信息和链接。
Your problems are mostly due to trying to subclass QThread. Even though the documentation recommends it, it is not the best way to use QThread. Please see this question and answer for more information and links.
我还没有弄清楚 startTimers 错误,尽管它可能与第一个错误有关。无论如何,您应该能够修复第一个错误。我在 Qt 中遇到过这个问题几次,我发现解决这个问题的“最佳”方法是创建一个初始化函数和一个 cleanUp 函数。该类的所有成员都是初始化为 NULL 的指针,直到调用 run 为止。请注意,“最佳”用引号引起来,因为肯定会有不同的意见,但它对我来说适用于大多数情况。
标题
实现
I haven't figured out the startTimers error although it could be related to the first one. In any case, you should be able to fix the first error. I have run into this problem in Qt a few times and I find this to be the "best" way to work around it is to create an initialize function and a cleanUp function. All members of the class are pointers that are initialized to NULL until run is called. Note that "best" is in quotes because there are sure to be differing opinions but it works for most situations for me.
Header
Implementation