27

プログラムを PyGTK から PyGObject イントロスペクションに初めて変換する過程にあり、スレッド化で障害にぶつかりました。完了するまでに時間がかかるプロセスがあるため、進行状況バーが表示されたダイアログをポップアップし、スレッドを使用してプロセスを実行し、進行状況バーを更新します。これは PyGTK では正常に機能しましたが、PyGObject に変換した後、通常の不適切なスレッド化の奇妙な現象がすべて発生します。プログラムはハングしますが、プロセスのさまざまな部分でハングしているように見えます。何を理解していません。

この簡単な PyGTK プログレスバーの例次に 示します。私はそれを PyGObject イントロスペクションに変換しましたが、私のプログラムと同じ問題が発生しました: ハングしたり、進行状況バーを適切に更新したりしません。

import threading
import random, time
from gi.repository import Gtk, Gdk
#Initializing the gtk's thread engine
Gdk.threads_init()


class FractionSetter(threading.Thread):
    """This class sets the fraction of the progressbar"""

    #Thread event, stops the thread if it is set.
    stopthread = threading.Event()

    def run(self):
        """Run method, this is the code that runs while thread is alive."""

        #Importing the progressbar widget from the global scope
        global progressbar 

        #While the stopthread event isn't setted, the thread keeps going on
        while not self.stopthread.isSet() :
            # Acquiring the gtk global mutex
            Gdk.threads_enter()
            #Setting a random value for the fraction
            progressbar.set_fraction(random.random())
            # Releasing the gtk global mutex
            Gdk.threads_leave()

            #Delaying 100ms until the next iteration
            time.sleep(0.1)

    def stop(self):
        """Stop method, sets the event to terminate the thread's main loop"""
        self.stopthread.set()

def main_quit(obj):
    """main_quit function, it stops the thread and the gtk's main loop"""
    #Importing the fs object from the global scope
    global fs
    #Stopping the thread and the gtk's main loop
    fs.stop()
    Gtk.main_quit()

#Gui bootstrap: window and progressbar
window = Gtk.Window()
progressbar = Gtk.ProgressBar()
window.add(progressbar)
window.show_all()
#Connecting the 'destroy' event to the main_quit function
window.connect('destroy', main_quit)

#Creating and starting the thread
fs = FractionSetter()
fs.start()

Gtk.main()

Gdk のスレッド機能のドキュメントでは、gdk_threads_init() を実行する前に g_thread_init(NULL) を実行する必要があることを強調しています。ただし、それを実行するには、追加のライブラリをいくつかリンクする必要があります。イントロスペクションを通じて GLib をインポートしようとしてから、GLib.thread_init() を実行しようとすると、次のエラーが発生します。

>>> from gi.repository import GLib
>>> GLib.thread_init(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
glib.GError: Could not locate g_thread_init: `g_thread_init': /usr/lib/libglib-2.0.so.0: undefined symbol: g_thread_init

これは、追加のスレッド ライブラリがリンクされていないためだと思います。これがスレッドの問題の原因である場合、これらのライブラリがリンクされているかのように GLib を操作するにはどうすればよいですか?

4

1 に答える 1

27

Python で書かれたいくつかの Gnome プログラム (この場合は Gnome Sudoku で、実際に何度か役に立ちました) を調べて、自分自身の質問に答えることができました。

秘訣は、C のドキュメントが示すようにGObject.threads_init()ではなく、コードの最初で呼び出す必要があることです。GLib.thread_init()

于 2011-08-04T22:46:14.447 に答える