阅读文档后我发现了这个:
The child of a
QObjectmust always be created in the thread where the parent was created. This implies, among other things, that you should never pass theQThreadobject (this) as the parent of an object created in the thread (since theQThreadobject itself was created in another thread).
我不太确定这意味着什么,所以我举了几个例子,想知道这适用于什么地方。
A.
class MyThread : public QThread {
MyThread(QObject *parent = 0) : QThread(parent) {
QNetworkAccessManager *test = new QNetworkAccessManager (this);
// here I assume that this child(test) will have the main thread (creator of MyThread)
// as it's parent and it will go horrible wrong.
}
....
}
B.
class MyThread : public QThread {
QNetworkAccessManager *test;
MyThread(QObject *parent = 0) : QThread(parent) {}
void run {
test = new QNetworkAccessManager(this);
// will the main thread be the parent here aswell?
// if I remove "this" this will work since its created in the thread (not the main thread)
}
....
}
好的,但是这个怎么样?
请注意,这些对象将像这样创建和启动:
MyThread *fakeThread = new MyThread; // should I or should I not pass "this" as a parent here?
QThread realThread;
fakeThread->moveToThread(&realThread);
realThread.start();
QMetaObject::invokeMethod(fakeThread, "start", Qt::QueuedConnection);
C.
class MyThread : public QObject {
MyThread(QObject *parent = 0) : QObject(parent) {
QNetworkAccessManager *test = new QNetworkAccessManager(this);
// I assume this constructor still will be create the the QNAM as a child to
// the main thread and it will not work
}
void start {
....
}
}
D.
class MyThread : public QObject {
QNetworkAccessManager *test;
MyThread(QObject *parent = 0) : QObject(parent) {}
void start {
test = new QNetworkAccessManager(this);
// What about now?
}
....
}
我真的很想实现选项 D,这样我就有了一个可以轻松删除的对象层级。例如,如果我想读取大量文件,并且我希望在线程终止时取消分配所有文件。
此外,QThread 派生版本与将 QObject 移动到线程的版本之间的主要区别是什么?文档总是说明在使用 Qthread 时该做什么和不该做什么,但我对此不太确定。
我现在最大的问题是我有一个派生自 QObject 的类,它将被移动到一个线程。在那个对象中我创建了另一个对象。该对象包含一个 QNetworkAccessManager 和一个 QFile。我将把“this”作为父级传递到哪里,或者在线程中时根本不应该这样做?请解释。
此刻,属于对象(uploader,它是一个线程)的对象(我们称它为RestHandler)是在堆上创建的。这是因为大多数函数都使用它,如果它是在堆栈上的头文件中创建的,那么它的父线程将是主线程。在 RestHandler 中,将在堆栈上创建一个 QNetworkAccessManager。
编辑:
阅读答案后,我尝试在堆栈上创建 restHandler 和 QNetworkAccessManager,然后移动它们。输出如下:
Resthandelerconstructor:restHandlercreated in threadQThread(0x22d5e8) with a accessManager in threadQThread(0x22d5e8) current location QThread(0x22d5e8)
然后,当我尝试移动 resthandler 时,我收到以下警告:
QObject::moveToThread: Current thread (0x1fbf0e0) is not the object's thread (0x22d5e8).
Cannot move to target thread (0x1fbf0e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x42a477c), parent's thread is QThread(0x22d5e8), current thread is QThread(0x4196f98)
我想有没有办法解决这个问题?该程序似乎可以运行并且在正确的线程中调用了插槽,但它崩溃之前似乎是一个时间问题。
最佳答案
来自Threads and QObjects documentation :
Event driven objects may only be used in a single thread. Specifically, this applies to the timer mechanism and the network module. For example, you cannot start a timer or connect a socket in a thread that is not the object's thread.
对您而言,这意味着您的QNetworkAccessManager 需要位于您将连接套接字等的线程中。它不能是您的MyThread 对象的子对象,如果它在您的构造函数中初始化,则需要在线程启动后将其移动到 MyThread。
You must ensure that all objects created in a thread are deleted before you delete the QThread. This can be done easily by creating the objects on the stack in your run() implementation.
在堆上分配 QNetworkAccessManager 是否有原因?你可以让它成为普通成员(在堆栈上)吗?
The Network Access API is constructed around one QNetworkAccessManager object, which holds the common configuration and settings for the requests it sends. It contains the proxy and cache configuration, as well as the signals related to such issues, and reply signals that can be used to monitor the progress of a network operation. One QNetworkAccessManager should be enough for the whole Qt application.
这向我表明,您可能需要重新考虑对此类对象使用多个线程背后的设计决策,以及您是否可以改为遵循预期的使用模式。您仍然可以有许多通过 threadsafe signal/slot connections 连接的工作线程到属于主线程的 QNetworkAccessManager 的单个实例。
关于c++ - Qt 在构建移动到线程的 QObject 时将 "this"作为父级传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9490166/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从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上找到一
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub