使用Qt信号/插槽而不是工作线程

时间:2010-04-01 09:22:16

标签: c++ qt

我正在使用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如何通过大量内置类来实现这一点,这些类似乎在单个线程上执行冗长的任务?

2 个答案:

答案 0 :(得分:4)

如果您在UI线程中执行长度作业,UI将会冻结。避免这种情况的一种方法是偶尔拨打一次QCoreApplication::processEvents()

在决定这样做之前,你应该非常小心地了解它的作用。调用此函数意味着GUI事件可以在您的操作过程中触发。如果这个事件可以反过来创造更多的工作,你可以在旧工作的中间开始新的工作。

我不会那么快地解雇工作线程方法。它具有将工作与GUI完全分离的优点,因此您可以确定开始的工作即将完成 您还应该考虑Windows特别有时会对GUI循环引入非平凡的延迟。如果主机有点忙或处于内存抖动状态,您会发现GUI事件可能需要几个很长的时间才能完成并将控制权返回给您的处理。

答案 1 :(得分:1)

将QThread与此类运行方法一起使用:

void run(){ exec(); }

这将提供另一个执行循环,您可以在这里执行“艰苦工作”,而无需实际冻结UI。

注意:确保通过添加

实际使用线程的执行循环
moveToThread(this);

在QThread派生的Thread类的构造函数的 end (文档没有多说明)