huyc

导航

没有银弹,合适与正确的距离

今天在网上查看QThread的信息时找到一篇文章,http://hi.baidu.com/cyclone/blog/item/5fac3bc7ab1b90d1d10060f2.html

文章引述了老外的观点说什么是QThread的正确使用方式,文章很短,一下子就看完了,看了无非就是说QThread的正确使用方式应该是事件驱动。

的确,标准的Qt程序就应该像这样:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char **argv){
QCoreApplication app(argc, argv);
qDebug<<"hello world";
return app.exec();
}

这里潜在的意思是说,如果用Qt,就应该利用其事件循环,所谓的正确的Qt的方式就是事件驱动编程。

事实上,Qt的很多类即使没有事件循环的存在也能工作得很好,丢弃事件循环的Qt依然有用,只能说,事件循环是充分利用Qt库的一种合适的方式,但不一定是正确的方式。

并不是为了博取噱头而故意混淆这样的概念,事件驱动是为了响应事件而设计的编程方式,像GUI程序基本上只能按事件驱动的方式来设计,用户随时可能对其下达指令,它需要捕获事件来响应用户,这里潜在的意思就是说,服务用户的程序就该像一个仆人一样,没事的时候等着,随时随地待命行事。

但不要忘了,无数的程序都是自己按照既定的“程序”在运行,这才是程序之所以是程序的运行方式,就好像很多的编程书名字那样,编程就像coke,按着cokebook就能完成任务,设想在厨房的时候,突然出现异步事件,我们可以去查看,程序也能,在Linux下,异步响应可以通过信号来完成。

可以发现,系统级别的中断提供了打断运行中的程序的途径,而用户级别是没有办法像系统那样可以在执行的代码中间更换控制流的,所以所谓的事件驱动其实都必须封装在一个事件循环之中,对于Qt的事件循环,随意一个函数调用就能阻断整个事件循环,正因为如此才会因为某一个函数导致整个程序无法响应的现象,不回到事件循环的控制流就无法处理任何的事件,甚至于其引以为傲的信号——槽机制,如果是排队连接,恐怕也无法处理了。

正因为如此,所谓的QThread的正确方式,只是为了更好地利用事件循环罢了,当然,也为了防止新手陷入迷惑——Qt一直声称其简化了C++的复杂性,而相比之言,一味地强调事件驱动反而更容易被迷惑,毕竟事件驱动的编程方式本身就不简单,而且,可以设想,顺序执行的程序可以很简单地加入异步事件,那如何在事件编程中加入顺序执行的程序呢?换句话说,有没有简单的方式可以用一种默认的动作来填补程序等待事件时的时间?这恐怕会使程序更加复杂,就如《C++ GUI Qt4编程》里面展示的那样,为了保持事件循环的持续响应,引入线程之外的实现方式将导致程序变得晦涩难懂,而引入线程增加的复杂性估计更吓人。

这让人想起面向对象和面向过程优越性的争论,如果抛开具体的应用,无论怎么说,都是有理,也无论如何,都没道理。从应用层面上说,没有正确的,只有合适的。

posted on 2011-12-03 21:11  huyc  阅读(303)  评论(0编辑  收藏  举报