我没有exec()在我的代码中调用,但是timer并且QUdpSocket工作正常.被exec()用于等待的event继续吗?
更新:timer工作正常,因为我没有打电话moveToThread(this)给QThread,这意味着它QThread实际上仍然是其中的一部分main thread.至于QUdpSocket我使用投票functions.所以它不需要合作signals.
提示:如果你需要做init一些东西,那需要event loop你的QThread,你可以delay打电话,moveToThread直到你不再需要它signals,这在程序加载时是实用的.您也不需要在构造函数中调用它run()(例如,您可以在内部调用它),只需将this QThread指针复制到变量并call使用指针在其他地方/其他地方生成.
使用PyQt4 4.8.6,下面的代码会产生错误
QObject :: startTimer:QTimer只能用于以QThread启动的线程
当a用作QApplication的变量时,如果cpp(或大多数其他)用于变量,它不会产生错误.这是PyQt4中的错误还是我缺少的东西?
#! /usr/bin/env python
# This is only needed for Python v2 but is harmless for Python v3.
import sip
sip.setapi('QVariant', 2)
from PyQt4 import QtGui
#def main():
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
use_a = False
print "Don't use a"
else:
use_a = True
print "Use a"
if use_a:
a = QtGui.QApplication(sys.argv)
else:
cpp = QtGui.QApplication(sys.argv)
model = QtGui.QStandardItemModel(4,2)
tableView = QtGui.QTableView()
tableView.setModel(model)
tableView.show()
if use_a:
sys.exit(a.exec_())
else:
sys.exit(cpp.exec_())
#if …Run Code Online (Sandbox Code Playgroud) 使用:C++ (MinGW),Qt4.7.4,Vista (OS),intel core2vPro
我需要以完全相同的方式处理2个巨大的文件.所以我想从2个单独的线程中为2个单独的文件调用处理例程.GUI线程没有什么重要的; 只显示一个标签并运行一个事件循环来检查线程终止条件的发射并相应地退出主应用程序.我预计这会同样地利用两个核心(intel core2),但相反,我从任务管理器看到其中一个核心被高度利用而另一个核心没有(尽管不是每次我都运行代码); 处理2个文件所花费的时间远远超过处理一个文件所花费的时间(我认为它应该相等或稍微多一点,但这几乎等于在非线程中一个接一个地处理2个文件应用).我可以以某种方式强制线程使用我指定的核心吗?
QThread* ptrThread1=new QThread;
QThread* ptrThread2=new QThread;
ProcessTimeConsuming* ptrPTC1=new ProcessTimeConsuming();
ProcessTimeConsuming* ptrPTC2=new ProcessTimeConsuming();
ptrPTC1->moveToThread(ptrThread1);
ptrPTC2->moveToThread(ptrThread2);
//make connections to specify what to do when processing ends, threads terminate etc
//display some label to give an idea that the code is in execution
ptrThread1->start();
ptrThread2->start(); //i want this thread to be executed in the core other than the one used above
ptrQApplication->exec(); //GUI event loop for label display …Run Code Online (Sandbox Code Playgroud) 我正在使用50 fps的摄像头(在Ubuntu环境和Qt框架中),每隔20 ms,我就会得到一个帧来处理.
我写了一个代码来从相机读取图像,然后将它们存储在硬盘中.
while(3.14)
{
cv::Mat Camera_Image = Capture_Image();
double T1 = (double)cv::getTickCount();
cv::imwrite (STORE_ADDRESS,Camera_Image);
T1 = (((double)cv::getTickCount() -T1)*1000)/cv::getTickFrequency();
print(T1);
}
Run Code Online (Sandbox Code Playgroud)
当我看到输出时,对于2048*1080图像尺寸,将单个图像写入硬盘的时间约为30毫秒.每个图像都是单通道(灰度)但我在硬盘中以.jpg格式编写它们.硬盘中每个图像的大小约为500K字节.
由于我在大约20毫秒内捕获一帧,我无法将它们全部写入硬盘实时.我已经使用Qthread编写了我的代码并创建了一个队列来查看是否有任何改进,但结果是相同的,它只是一个内存开销.
是否有可能改变这种情况,或使用其他库将这些图像更快地写入硬盘?如果可以的话,我也更喜欢Qt解决方案......
另外我需要将每一帧写入硬盘,所以请不要使用Motion压缩算法,因为它们不适用于我的情况....
代码:Mainwindow.cpp
Qlist<cv::Mat> FINAL_IM_VEC;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
IMREAD *IMR = new IMREAD(this); // an instance of IMREAD Class which reads camera frames
IMWRITE *IMW = new IMWRITE(this); // an instance of IMWRITE Class which Writes camera frames into hard disk
QThread *IMAGE_READ_Thread = new QThread(this);
QThread *Image_Store_Thread = new QThread(this); …Run Code Online (Sandbox Code Playgroud) 按照官方文档,我正在尝试这样做:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QThread *thread = new QThread;
Worker *worker= new Worker();
worker->moveToThread(thread);
//init connections
thread->start();
}
Run Code Online (Sandbox Code Playgroud)
工人构造函数:
Worker::Worker(QObject *parent) :
QObject(parent)
{
serial = new QSerialPort(this); //passing the parent, which should be the current thread
}
Run Code Online (Sandbox Code Playgroud)
没有编译错误但是当我执行它时会抛出这个:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x11bd1148), parent's thread is QThread(0x11bd2ef8), current thread is QThread(0x3e47b8)
Run Code Online (Sandbox Code Playgroud)
也就是说,它告诉我serial作为父线程的主线程而不是我创建的线程.
如果我不在构造函数中实例化序列但在主进程中实例化相同的结果,这是在我们调用之后触发的thread->start():
Worker::Worker(QObject *parent) :
QObject(parent)
{
}
Worker::doWork()
{
if(!serial) …Run Code Online (Sandbox Code Playgroud) 我写了一个执行工作对象的线程。一切正常。结果信号也按应有的方式发出。当然,我处理了有关线程/对象关联性的常见错误。
今天我为这些工作线程/线程编写了一个自动化模块测试。我创建了一个 QSignalSpy 来等待工作对象(已移动到线程)发出的信号,如下所示:
QSignalSpy spy(worker, SIGNAL(Success()));
thread.ExecuteWorker();
QVERIFY(spy.wait()); // Error in this line
Run Code Online (Sandbox Code Playgroud)
我在标记行中收到一个众所周知的错误:
QObject::killTimer: timers cannot be stopped from another thread
Run Code Online (Sandbox Code Playgroud)
首先,我预计会出现错误,因为 wait() 中的某些代码在错误的线程中执行。然后我在QSignalSpy的实现中发现了如下代码:
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0))
{
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
Run Code Online (Sandbox Code Playgroud)
这显然意味着 QSignalSpy 一直使用 DirectConnection 并且不能用于监视生活在不同线程中的对象的信号。
为什么他们在 Qt5.3 中这样编程?这是一个错误还是有意的行为?我该如何解决这个限制?
假设我们在QObject-deriving类中编写了一个非const方法:
class MyClass : public QObject {
int x;
public:
void method(int a) {
x = a; // and possibly other things
};
};
Run Code Online (Sandbox Code Playgroud)
我们希望使该方法成为线程安全的:意味着从任意线程调用它,并且同时从多个线程调用它,不应该引入未定义的行为.
Qt提供了哪些机制/ API来帮助我们使该方法具有线程安全性?
Qt的哪些机制/ API可以在方法执行"其他事情"时使用?
是否可以对"其他事物"进行分类,以便为使用Qt特定的机制/ API提供信息?
非主题是C++标准本身提供的机制,以及确保线程安全的通用/非Qt特定方式.
基本上我需要在Java中完成同样的事情:
SwingUtilities.invokeLater(()->{/* function */});
Run Code Online (Sandbox Code Playgroud)
或者在javascript中这样:
setTimeout(()=>{/* function */}, 0);
Run Code Online (Sandbox Code Playgroud)
但是用Qt和lambda.所以有些伪代码:
Qt::queuePushMagic([]() { /* function */ });
Run Code Online (Sandbox Code Playgroud)
作为一个额外的复杂性,我需要这个在多线程上下文中工作.我实际上要做的是在正确的线程中自动运行某些方法.那么代码看起来如何:
SomeClass::threadSafeAsyncMethod() {
if(this->thread() != QThread::currentThread()) {
Qt::queuePushMagic([this]()=>{ this->threadSafeAsyncMethod() });
return;
}
}
Run Code Online (Sandbox Code Playgroud)
这该怎么做?
我有一个创建 QRunnables 并在 QThreadPool 实例中启动它们的类。
我的线程运行良好,但如果用户想退出应用程序,应用程序需要很长时间才能停止。当然是因为发起的请求需要时间。
这是我如何使用 QThreadPool、QRunnables 的片段代码:
import sys
from PyQt5.Qt import QThreadPool, QApplication, QWidget, QVBoxLayout
from PyQt5.Qt import QTimer, QObject, QPushButton, QLabel
from PyQt5.Qt import QRunnable
class BackendQRunnable(QRunnable):
"""
Class who create a QThread to trigger requests
"""
def __init__(self, task):
super(BackendQRunnable, self).__init__()
self.task = task
def run(self):
"""
Run the QRunnable. Trigger actions depending on the selected task
"""
# Here I make long requests
if 'user' in self.task:
self.query_user_data()
elif 'host' in self.task:
self.query_hosts_data()
elif …Run Code Online (Sandbox Code Playgroud) QObject当它们的工作线程在它们之前完成时,s 很容易变成无线程的。发生这种情况时,Qt 不会释放它们的计时器 ID,即使计时器不再处于活动状态。因此,出现QBasicTimer::stop: Failed. Possibly trying to stop from a different thread警告。它主要是外观上的后果,但确实表明计时器 id 泄漏,因此有一个解决方法会很好。下面的例子触发了这个问题:
#include <QtCore>
int main(int argc, char *argv[]) {
static_assert(QT_VERSION < QT_VERSION_CHECK(5,11,0), "");
QCoreApplication app(argc, argv);
QObject object;
object.startTimer(1000);
QThread workThread;
workThread.start();
object.moveToThread(&workThread);
QTimer::singleShot(500, &QCoreApplication::quit);
app.exec();
workThread.quit();
workThread.wait();
}
Run Code Online (Sandbox Code Playgroud)
如果解决方法不必对定时器的分配方式进行任何修改,那就太好了,即除了 Qt 已经做的之外,不需要额外的定时器跟踪。
qthread ×10
qt ×9
c++ ×6
pyqt ×2
qtcore ×2
event-loop ×1
lambda ×1
opencv ×1
pyqt4 ×1
pyqt5 ×1
python ×1
qsignalspy ×1
qtestlib ×1
qtimer ×1
qtserialport ×1