2010-04-01 85 views
2

我正在使用Qt并希望编写一个类来执行一些类似于FTP/HTTP的网络类型操作。该类需要依次连接到大量机器,但我需要应用程序UI在此过程中保持(相对)响应,因此用户可以取消操作,退出应用程序等。我的第一个想法是使用一个独立的网络线程,但内置的Qt FTP/HTTP(和其他)类显然避免使用线程,而是依赖于信号和插槽。所以,我希望做同样的事情,并希望我可以做这样的事情:使用Qt信号/插槽而不是工作线程

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

如果您想要确保插槽在发出信号时排队,您可以将其指定为连接功能的最终参数。 – 2010-04-01 17:37:36

回答

3

如果您在UI线程中执行一项长工作,UI将冻结。避免这种情况的一种方法是在一段时间内拨打电话QCoreApplication::processEvents()

但是你应该非常小心,但是在你决定做这件事之前,要明白它的作用。调用这个函数意味着一个GUI事件可以在操作过程中触发。如果这个事件又可以创造更多的工作,那么你可以在旧工作中间开始一项新工作。

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

+0

我只是查找QThread,它是a)易于实现,b)像任何其他QObject一样支持信号/插槽。感谢您的建议。 – Rob 2010-04-01 09:54:29

2

使用的QThread有这样的run方法:

void run(){ exec(); } 

这将提供另一执行循环,在那里你可以做你的“努力工作”,而不实际上可以冻结UI。

注:确保实际上在你的QThread派生Thread类的构造函数的年底加入

moveToThread(this); 

使用线程的执行循环(DOC没有说太多关于它)

+0

http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ – alisami 2011-04-22 17:19:06

+0

正如您在离开我的评论后发布artice的日期所见。到那个时候,关于如何做到这一点的唯一参考是Qt文档,它说明了这一点以及Qt示例。 – drahnr 2011-04-23 06:18:34