假设我调用QtConcurrent::run()哪个在工作线程中运行一个函数,并在该函数中动态分配几个QObject(供以后使用).由于它们是在工作线程中创建的,因此它们的线程关联应该是工作线程的线程关联.但是,一旦工作线程终止,QObject线程关联就不再有效.
问题:Qt是自动将QObjects移动到父线程中,还是我们负责在工作线程终止之前将它们移动到有效线程?
我似乎无法QtConcurrent::run()仅使用简单的函数与方法(类的函数成员)关联.我怎样才能做到这一点?
使用常规功能,我无法发出信号和拖拽.为什么有人会发现这是一个更好的替代品QThread超出我的想法,并希望得到一些投入.
的QFuture类有方法,例如cancel(),progressValue()等.这些可明显通过被监测QFutureWatcher.但是,QtConcurrent::run()读取文档:
请注意,QtConcurrent :: run()返回的QFuture不支持取消,暂停或进度报告.返回的QFuture只能用于查询运行/完成状态和函数的返回值.
我实际上可以创建一个QFuture可以取消的方法,并报告单个长时间运行的操作的进度,这看起来是徒劳的.(看起来可能QtConcurrent::map()和类似的功能可以,但我只有一个长期运行的方法.)
(对于熟悉.Net的人来说,就像BackgroundWorker班级一样.)
有哪些选择?
假设您的应用程序需要在多个线程中运行一个函数,其数量大于CPU核心/线程的数量.一种方法是使用QtConcurrent和设置最大线程数:
MyClass *obj = new MyClass;
QThreadPool::globalInstance()->setMaxThreadCount(30);
for(int i=0;i<30;i++)
QtConcurrent::run(obj, &MyClass::someFunction);
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用多个对象并将它们移动到不同的线程moveToThread:
for(int i=0;i<30;i++)
{
MyClass *obj = new MyClass;
QThread *th = new QThread();
obj->moveToThread(th);
connect(th, SIGNAL(started()), obj, SLOT(someFunction()) );
connect(obj, SIGNAL(workFinished()), th, SLOT(quit()) );
connect(th, SIGNAL(finished()), obj, SLOT(deleteLater()) );
connect(th, SIGNAL(finished()), th, SLOT(deleteLater()) );
th->start();
}
Run Code Online (Sandbox Code Playgroud)
由于线程数大于CPU核心数,因此在运行时应该在不同的核心之间切换线程.
问题是这两种方法是否有不同的表现?即,切换是否QThread与使用QtConcurrent::run?的切换不同?
主GUI线程在等待QFuture时更新QProgressDialog的正确方法是什么.具体来说,这个循环中的内容:
QProgressDialog pd(...);
QFuture f = ...;
while (!f.isFinished()) {
pd.setValue(f.progressValue());
// what goes here?
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个sleep()就像在那里调用,但这不是最佳的(并且当然会引入一些GUI延迟).
如果我什么也没放,主线程将循环极点pd.setValue(),浪费CPU周期.
我希望放置像QCoreApplication :: processEvents(flags,maxtime)这样的东西,但如果事件队列为空则立即返回.我想要一个等待maxtime或者即使队列为空的版本.这样,我得到了延迟,主线程随时准备响应GUI事件.
我正在考虑运行异步代码的两个选项:Qt Concurrent和std::async.鉴于我正在使用Qt编写GUI应用程序,因此使用Qt Concurrent是有意义的.然而std::async,所有主要编译器似乎也很好并且支持.
我应该使用Qt Concurrent还是std::async新代码?比较两者时我还应该寻找什么呢?
如果我使用 启动一些用于异步执行的函数QtConcurrent::run,并使用 a 监视返回的 future QFutureWatcher,那么如果我可以在该异步执行函数中执行一些操作来传达一些进度文本,这将导致触发QFutureWatcher其progressTextChanged信号,该怎么办?
即我想做的是这样的:
void fn() {
???->setProgressText("Starting);
...
???->setProgressText("halfway");
...
???->setProgressText("done!");
}
QFutureWatcher watcher;
connect(&watcher, SIGNAL(progressTextChanged(const QString&)), &someGuiThing, SLOT(updateProgress(const QString&)));
connect(&watcher, SIGNAL(finished(), &someGuiThing, SLOT(doStuff()));
QFuture<void> future=QConcurrent::run(fn);
watcher.setFuture(future);
Run Code Online (Sandbox Code Playgroud)
然而,大问题是,QtConcurrent::run文档明确指出
请注意,QtConcurrent::run() 返回的 QFuture 不支持 取消、暂停或进度报告。返回的QFuture只能用于查询函数的运行/完成状态和返回值。
那么,我能做的最简单的事情是什么,它能让我得到与上面试图做的功能相同的东西呢?我必须放弃吗QtConcurrent::run?QFuture?两个都?(然后返回QThread并排队连接?)
我QtConcurrent::run用来运行一个函数,并通过引用传递值,但值的内存地址是不同的.
但是如果我通过指针传递值,地址是一样的!我无法弄清楚.我错过了什么吗?
这是代码.
void ptr(QString* s)
{
qDebug() << "pass by ptr: " << s;
}
void ref(QString& s)
{
qDebug() << "pass by ref: " << &s;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString str;
QFuture<void> f1 = QtConcurrent::run(ptr, &str);
f1.waitForFinished();
QFuture<void> f2 = QtConcurrent::run(ref, str);
f2.waitForFinished();
qDebug() << "address of str: " << &str;
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
输出:
pass by ptr: 0x28fefc
pass by ref: 0x525de4
address of str: 0x28fefc
Run Code Online (Sandbox Code Playgroud) 我编写了一个多线程程序,它通过大量浮点运算来执行一些CPU繁重的计算.更具体地说,它是一个逐帧比较动画序列的程序.即它将动画A中的帧数据与动画B中的所有帧进行比较,对于动画A中的所有帧.我对不同动画并行执行此强化操作,因此程序可以处理AB对,BC对和CA对在平行下.该程序使用QtConcurrent和"map"函数,该函数将带有运动的容器映射到函数上.QtConcurrent为我管理线程池,我正在使用英特尔四核处理器,因此它产生了4个线程.
现在,问题是我的进程会破坏我的CPU.用法是100%不变的,如果我在一个足够大的运动集上运行我的程序(非分页区域中的页面错误),我实际上得到了一个蓝屏死机.我怀疑这是因为我的电脑超频了.但是,这可能是因为我编写程序的方式吗?我用来测试机器稳定性的一些非常密集的benchamrking工具从未使我的PC崩溃.有没有办法控制我的程序如何使用我的CPU来减少负载?或许我误解了我的问题?
是否可以通过其关联的QFuture对象来停止线程?目前我一直在开始这样的视频捕捉过程.
this->cameraThreadRepresentation = QtConcurrent::run(this,&MainWindow::startLiveCapturing);
Run Code Online (Sandbox Code Playgroud)
在startLiveCapturing-Method内部运行一个无限循环,捕获图像并显示它们.因此,如果用户想要停止该过程,则只需按下按钮即可停止该操作.但似乎我不能通过调用这样的取消方法来阻止这个线程?
this->cameraThreadRepresentation.cancel();
Run Code Online (Sandbox Code Playgroud)
我做错了什么,我怎么能停止该线程或操作.