我正在使用Qt并希望编写一个类,它将执行一些网络类型的操作,类似于FTP / HTTP。该类需要一个接一个地连接到许多机器,但我需要应用程序UI在此过程中保持(相对)响应,因此用户可以取消操作,退出应用程序等。我的第一个想法是使用网络内容的单独线程,但内置的Qt FTP / HTTP(和其他)类显然避免使用线程,而是依赖信号和插槽。所以,我想做类似的事情,并希望我可以这样做:
class Foo : public QObject
{
Q_OBJECT
public:
void start();
signals:
void next();
private slots:
void nextJob();
};
void Foo::start()
{
...
connect(this, SIGNAL(next()), this, SLOT(nextJob()));
emit next();
}
void Foo::nextJob()
{
// Process next 'chunk'
if (workLeftToDo)
{
emit next();
}
}
void Bar::StartOperation()
{
Foo* foo = new Foo;
foo->start();
}
然而,在所有操作完成之前,这不起作用并且UI冻结。我希望发射信号不会立即调用插槽,但会以某种方式排队等待Qt,从而允许主UI仍在运行。
那么我需要做些什么来使这项工作? Qt如何通过大量内置类来实现这一点,这些类似乎在单个线程上执行冗长的任务?
答案 0 :(得分:4)
如果您在UI线程中执行长度作业,UI将会冻结。避免这种情况的一种方法是偶尔拨打一次QCoreApplication::processEvents()
。
在决定这样做之前,你应该非常小心地了解它的作用。调用此函数意味着GUI事件可以在您的操作过程中触发。如果这个事件可以反过来创造更多的工作,你可以在旧工作的中间开始新的工作。
我不会那么快地解雇工作线程方法。它具有将工作与GUI完全分离的优点,因此您可以确定开始的工作即将完成 您还应该考虑Windows特别有时会对GUI循环引入非平凡的延迟。如果主机有点忙或处于内存抖动状态,您会发现GUI事件可能需要几个很长的时间才能完成并将控制权返回给您的处理。
答案 1 :(得分:1)
将QThread与此类运行方法一起使用:
void run(){ exec(); }
这将提供另一个执行循环,您可以在这里执行“艰苦工作”,而无需实际冻结UI。
注意:确保通过添加
实际使用线程的执行循环moveToThread(this);
在QThread派生的Thread类的构造函数的 end (文档没有多说明)