我的 Qt 5.7(在 Windows 10 上)应用程序中遇到了一个奇怪的错误,并且找不到导致这种行为的常见罪魁祸首:
完整的错误信息是
QObject::moveToThread: Current thread (0x2afcca68) is not the object's thread (0x34f4acc8). Cannot move to target thread (0x34f4adc8)
QObject::setParent: Cannot set parent, new parent is in a different thread
这也是我的代码:
main.cpp
#include <QApplication>
#include <QQuickItem>
#include "CustomQuickWidget.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
const QUrl source = QUrl(QLatin1String("qrc:/main"));
CustomQuickWidget widget(source);
return app.exec();
}
main(main.qml 的别名):
// You can put any random QML content in this case really as long as it doesn't create a window since the CustomQuickWidget does that.
Rectangle {
id: window
visible: true
width: 600
height: 480
}
CustomQuickWidget.cpp
#include "CustomQuickWidget.h"
#include <QQuickItem>
CustomQuickWidget::CustomQuickWidget(const QUrl &source, QWidget *parent) : QQuickWidget(source, parent) {
// Setup the recognizer
this->airWheelRecognizer = new QAirWheelGestureRecognizer();
this->airWheelType = QGestureRecognizer::registerRecognizer(airWheelRecognizer);
// and turn on grabbing for all the supported gestures
grabGesture(airWheelType);
grabGesture(Qt::SwipeGesture);
grabGesture(Qt::TapGesture);
// Create thread and device worker
this->deviceThread = new QThread(this);
this->deviceWorker = new DeviceMapper(this, Q_NULLPTR); // NOTE: this here is NOT for parent. The constructor's signature for this class is: DeviceMapper(QObject* receiver, QList<Qt::GestureType>* gestureIDs, QObject* parent = Q_NULLPTR)
this->deviceWorker->init();
// Create timer that will trigger the data retrieval slot upon timeout
this->timer = new QTimer();
this->timer->setTimerType(Qt::PreciseTimer);
this->timer->setInterval(5);
// Move timer and device mapper to other thread
this->timer->moveToThread(this->deviceThread);
this->deviceWorker->moveToThread(this->deviceThread); // FIXME For unknown reason: QObject::moveToThread: Current thread (...) is not the object's thread. Cannot move to target thread
// Connect widget, timer and device mapper
createConnections();
// Run thread
this->deviceThread->start();
// Connect device and start data retrieval
QTimer::singleShot(0, this->deviceWorker, &(this->deviceWorker->slotToggleConnection));
QTimer::singleShot(0, this->deviceWorker, &(this->deviceWorker->slotToggleRun));
this->show();
}
CustomQuickWidget::~CustomQuickWidget()
{
if (this->deviceThread) {
this->deviceThread->quit();
this->deviceThread->wait();
}
}
void CustomQuickWidget::createConnections()
{
connect(this->timer, SIGNAL(timeout()),
this->deviceWorker, SLOT(slotRetrieveData()));
connect(this->deviceThread, SIGNAL(started()),
this->timer, SLOT(start()));
connect(this->deviceThread, SIGNAL(finished()),
this->deviceWorker, SLOT(deleteLater()));
connect(this->deviceThread, SIGNAL(finished()),
this->deviceThread, SLOT(deleteLater()));
}
bool CustomQuickWidget::event(QEvent* event) {
if (event->type() == QEvent::Gesture) {
bool res = gestureEvent(static_cast<QGestureEvent*>(event)); // Not important so not included as code here
return res;
}
return QWidget::event(event);
}
如您所见,我这里有一个典型的工作线程。我已确保我的工作人员(此处为 DeviceMapper)没有父级。它也在我的小部件内实例化(QThread 也被创建)但与计时器一起移动到线程。
现在除了标题中的明显问题外,我还必须提及以下内容:
this->timer->moveToThread(this->deviceThread);时没有报错我的其他应用程序和这个应用程序之间的唯一区别是 QQuickWidget(而不是 QWidget)和 QML 的使用。我对 QML 很陌生,这也是我的第一个 QQuickWidget,所以我可能会遗漏一些需要“激活”的明显设置。
我也添加了
cout << this->deviceWorker->thread()->currentThreadId() << endl;
cout << this->thread()->currentThreadId() << endl;
就在 this->deviceWorker->moveToThread(this->deviceThread); 之前,我得到了
0x18b0
0x18b0
这意味着在 moveToThread(...) 之前,我的对象属于实例化 QThread 的同一个线程。在 moveToThread(...) 之后打印线程 ID 返回相同的结果,但这是预期的,因为未能将对象正确移动到另一个线程。
更新:
只有在 Release模式下构建时才会出现错误消息,但是无论构建类型如何,我的错误仍然存在。
最佳答案
我已经设法通过查明问题发生的时间来解决我的问题。
在上周结束时,我正在编写的应用程序突然开始工作,所以尽管我很困扰为什么之前发生的所有事情,但我还是顺其自然。我既没有更改库的代码(除了我的代码中的一些注释显然不会影响代码本身),也没有更改我的 QML 应用程序的 C++ 代码。我所更改的只是我的 QML,但实际上与下面的 C++ 代码无关。我唯一改变的是构建类型。但是我上周并没有真正注意到这一点。
昨天我开始了一个新项目。在第一次运行后,我遇到了同样的问题。这让我抓狂。所以我开始分析我的代码(@Kuba Ober,对不起,伙计,但是发布完整的代码甚至库的一小部分是不可能的,否则我会这样做(即使它有几百行实际代码(不包括评论和空行之类的东西))。我检查并仔细检查了父子关系,但找不到任何可以给我哪怕是一个小提示的东西,什么时候以及为什么会发生这种情况。我还分析了堆栈以尽我所能,但一切都是徒劳的。
然后我突然想到...我在上面提到过,我以前的项目在更改其构建类型 后突然开始工作。在我的处境中,这确实是万恶之源。我将我的库添加到我的项目中的方法(不包括与库一起属于同一 subdir 项目的初始库)是在我的新项目的根目录中创建一个名为 libs 并将相关内容复制到其中。现在,在我完成我的库并进行一些测试后,我显然决定切换到发布版本。但是,我将 release 模式下的库构建复制到 debug 模式下构建的项目。因此,在多次重建并在各处复制库之后,我发现混合使用该库的应用程序的构建类型和库本身会导致此问题。
我知道混合构建类型是一个坏主意,而且我通常不会那样做,但这次我只是忘记了,完全是个意外。当具有 X 构建类型的应用程序和具有 Y 构建类型的库混合使用时,我不知道内部发生了什么,但我的结果是我在此线程中发布的错误。
感谢大家的帮助。我从你的评论中学到了很多东西!尽管在我的情况下不需要调试,但我很感激你。 :)
关于c++ - Qt 无法将目标移动到线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38850077/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类