K's Diary


このページは、たわいのない日々のウワゴトを綴るページです。
なんてツマラナソウナページなんだ(笑)

一応、内容毎にタイトルの色を変えています。
緑色はlinuxに関する話題、 黄色はコンピュータゲームに関する話題、 水色はその他の話題になっています。
なお、スタイルシートに対応していないブラウザでは、 色は変わりませんのであしからず。


過去の日記

全てのトピックを表示


'10/6/25

■ GTK+のスレッド処理

GTK+でスレッドを使う場合の注意点は、GTK+のFAQの通り。

…なんだけど、Win32だとハングアップする事がある。
全くダメ、というわけではないのだけど、例えばメッセージダイアログを作って表示しようとする、など。
まぁ、Windowsで複数スレッドでGUIを操作するとヤバい、という話をチラホラ聞くので、 何となくアイドルコールバックに登録させて、そちらで表示させたら、 ハングアップしなくなりました。

以下、実験に使ったソース。
pythonだけど、C言語でも検証しているので、PyGTKの問題じゃないと思う。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
import time

import pygtk
pygtk.require("2.0")
import gtk, gobject

class Thread(gobject.GObject, threading.Thread):
__gsignals__ = {
"end": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
}

def __init__(self):
gobject.GObject.__init__(self)
threading.Thread.__init__(self)

def do_end(self):
print("do_end().")

def run(self):
time.sleep(3)
self.emit("end")

gobject.type_register(Thread)

class MyWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
self.thread = None

button = gtk.Button("Start!")
button.show()
self.add(button)
button.connect("clicked", self.on_start)

def on_start(self, button):
button.set_sensitive(False)
self.thread = Thread()
self.thread.connect("end", self.on_thread_end, button)
self.thread.start()

def on_thread_end(self, thread, button):
gtk.gdk.threads_enter()

self.thread = None
button.set_sensitive(True)

dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Thread End.")
dialog.connect_after("response", self.on_response)

# --- ここで、表示するとハングする。
#dialog.show()
# --- なので、次のアイドル待ち状態になったら表示するようにする。
gobject.idle_add(self.on_idle_once, dialog)

gtk.gdk.flush()
gtk.gdk.threads_leave()

def on_response(self, dialog, response):
dialog.destroy()

def on_idle_once(self, dialog):
dialog.show()
return False

if __name__ == "__main__":
gtk.gdk.threads_init()

window = MyWindow()
window.connect("destroy", gtk.main_quit)
window.show()

gtk.gdk.threads_enter()
gtk.main()
gtk.gdk.threads_leave()