17.1 什么时候使用多线程,什么时候不要使用

线程基本上来说是你的应用程序中一条单独的执行路径.有些地方把线程成为轻量级的进程,但是线程和进程有着一个最本质的区别,那就是:进程是在不同的地址空间运行的,而同一个进程内的所有的线程都在同一个地址空间运行. 当然这样的好处是,同一个进程的线程互相访问公共的数据是非常方便的,不过这也造成了另外一个经常犯错误的地方,就是很一个数据很容易被多个线程同时访问,造成不可知的后果,因此强烈推荐对于这些数据的访问,必须小心的使用用于同步变量访问的变量,比如信号量和关键区域.

如果使用的当,多线程编程可以简化应用程序的体系结构,并且将用户界面和其后面的真实世界分割开来.注意这通常不会让你的应用程序运行的更快,除非你有多个处理器,但是用户界面通常会变得更灵敏.

wxWidgets既提供了线程的支持,也提供了信号量和带条件的关键区域的支持.其线程API主要参考的是pthread(POSIX线程)模型,不过某些API采用了不同的名字,而另外一些API则吸收了部分Win32线程API的灵感.

这些类使得编写多线程的程序变得简单,并且还提供了相对于本地线程API更多的错误检查.尽管如此,多线程编程仍然不是一个很简单的事情,对于大型的项目尤其如此.因此,在考虑编写新的多线程程序或者在旧的代码中加入多线程之前,仔细的考虑一下是不是应该采取可选的替代方案来实现同样的功能,是一件很值得一做的事情.在有些情况下,线程是唯一最优的选择,比如对于一个FTP服务器来说,为每一个新的连接创建一个线程,但是,如果只是增加一个线程来为某个长时间的运算显示一个进度条来说,这种线程的时候就有点过犹不及了.在这种情况下,你可以将计算任何放在系统空闲的时候进行,并且周期性的调用wxWindow::Update来更新用户界面就可以了.关于这个问题更详细的描述,请参考本章的最后一节,"多线程的替代方案"中的描述.

如果你还是决定在你的代码中使用多线程,我们强烈建议你只在你的主线程中调用所有和GUI有关的函数.尽管wxWidgets自带的线程例子中演示了怎样在多个线程中同时调用GUI函数,但是,一般来说,这是非常非常差劲的设计.一个主线程负责GUI,其它多个线程负责别的计算工作,他们之间通过事件互相通讯,这样的设计是更好的设计并且通常可以避免很多的错误从而节约你大量的调试的时间.比如说,在Win32平台上,线程只能使用由自己而不是别的线程创建的GUI对象(画笔,画刷之类).

要实现线程之间通讯,你可以使用wxEvtHandler::AddPendingEvent函数或者它的简化版本wxPostEvent,这些函数被设计成线程安全的因此你可以使用他们在线程之间发送事件.