PyGTK 多线程

来源:互联网 发布:随身带着淘宝去异界301 编辑:程序博客网 时间:2024/05/01 20:15

当PyGTK升级到2.4之后,不知是我的错误还是PyGTK的bug,很多与多线程有关的调用都发生了错误。这两天,我花了很多时间来修改coralftp中关于线程的问题,现在总结一下。

    PyGTK是可以支持多线程的,在多线程程序的头部,必须有一个gtk.threads_init()调用,否则程序会运行地出奇地慢并伴随各种错误。

    PyGTK 多线程的编程一般有两种模型,一种是通过gtk.threads_enter()和gtk.threads_leave()来进入和退出临界区,一遍让多 个线程顺序地访问GTK的资源。在这种模型下,需要搞清楚PyGTK合适自动进入临界区,何时不会自动进入。比较麻烦的是当响应GUI事件的方法时,会自 动进入临界区,但在响应idle_add、timeout等事件时则不会,因为有时很难判断一个函数究竟是由idle_add调用的还是响应了某个事件。 即便可以判断,这种方式也是比较麻烦的,因为对于有大量界面工作的程序而言,想要每一次都正确地进出临界区,可能要写大量的代码。而调试也是这类程序的麻 烦。

    另一种方法是只在主线程中使用GTK的资源,其他的线程则通过gtk.idle_add()的方式来执行访问GTK资源的函数。这种方法相对于上一种而言,是容易了很多了,但也有一些需要特别注意的地方。
     1. 由于在主线程中也没有使用临界区,所以在编程过程中是不能使用临界区的,即这种方法不能和第一种混淆。
     2.
gobject有事件的机制,其事件机制是可以在其他的线程中使用的,并且,当通过emit触发事件时,事件的响应程序是在触发事件的线程中运行的,而不 是在主线程或GTK线程中运行的。因此响应事件的函数如果希望在主线程中运行,仍然需要使用gtk.idle_add()。
     3. GTK的timeout和监控文件流的机制最好不要在非GTK线程中使用,虽然理论上它们应该是可用的。这两个东西完全可以用Python的threading.Timer和select.poll()来代替。
     4. 在通过idle_add运行的函数中,是不能使用Dialog的run()方法的,否则也会造成死锁。Dialog的run()方法可以用show()和 set_modal(True)来代替,并且通过编写一个响应’response’事件的函数在必要的时候执行其destroy()方法就可以了。

    虽然还是有一些小的bug,但Python + GTK2仍不失为一个强大的组合:GTK2的pretty加上Python的powerful、flexibe,我们完全可以用它们编写出功能强大、界面友好、运行快速的桌面应用程序。