3

だから私は一定の時間の後にウェブサイトからの更新をチェックする必要があるアプリケーションを書くのに忙しいです、私はGtk+3でpythonを使用しています

main.pyファイル

class Gui:
    ...
    def on_update_click():
        update()

app=Gui()
Gtk.main()

update.pyファイル

def update():
    #check site for updates
    time.sleep(21600) #check again in 6hrs

スレッドを使用する必要があると思います。私の考えは:

Gtk.main()はメインスレッドを実行します。

ユーザーが更新ボタンをクリックすると、update()がバックグラウンドで実行されます。#スレッド2

私の考えは正しいですか、それとも何かを逃したことがありますか?

編集:わかりました、
on_update_click関数:

            Thread(target=update).start(). 

K、コンピュータはもうフリーズしません:D

つまり、Gtk.main()を閉じたときにのみ、更新スレッドが開始されるだけです。UIを閉じても更新が続くのは良いことですが、UIが上がったときにも更新を開始したいと思います。

4

3 に答える 3

7

だから私はついにそれを機能させることができました。私は言う必要がありました:

from gi.repository import Gtk,GObject

GObject.threads_init()
Class Gui:
    .....
    ......
    def on_update_click():
            Thread(target=update).start()

最初に私は使用しました:

thread.start_new_thread(update())

on_update_click 関数で。私のJFセバスチャンが述べたように、これはすぐにこのスレッドを呼び出すため、これは正しくありませんでした. これにより、コンピューター全体がフリーズしました。

次に、次のように追加しました。

Thread(target=update).start()

on_update_clicked 関数は、メイン スレッド Gtk.main() が閉じられた後にのみ機能しました。そのため、スレッドは同時に実行されていませんでした。

追加: GObject.threads_init()

これにより、スレッドが Python インタープリターに対してシリアルに実行できるようになりました: Threads in Gtk !

于 2012-08-15T05:23:02.957 に答える
4

thread.start_new_thread(update())間違っている。メインスレッドですぐに呼び出されるため、モジュールを直接update()使用しないでください。代わりにモジュールをthread使用してください。threading

を呼び出しthreading.current_thread()て、どのスレッドが実行されるかを調べることができますupdate()

コードを簡素化するには、すべての gtk コードをメイン スレッドで実行し、ブロッキング操作を使用して Web ページを取得し、バックグラウンド スレッドで実行します。

GTK+ 3 チュートリアルの拡張例に基づく:

#!/usr/bin/python
import threading
import urllib2
from Queue import Queue

from gi.repository import Gtk, GObject

UPDATE_TIMEOUT = .1 # in seconds

_lock = threading.Lock()
def info(*args):
    with _lock:
        print("%s %s" % (threading.current_thread(), " ".join(map(str, args))))

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Hello World")

        self.button = Gtk.Button(label="Click Here")
        self.button.connect("clicked", self.on_button_clicked)
        self.add(self.button)

        self.updater = Updater()
        self._update_id = None
        self.update()

    def on_button_clicked(self, widget):
        info('button_clicked')
        self.update()

    def update(self):
        if self._update_id is not None: 
            GObject.source_remove(self._update_id)

        self.updater.add_update(self.done_updating) # returns immediately
        # call in UPDATE_TIMEOUT seconds
        self._update_id = GObject.timeout_add(
            int(UPDATE_TIMEOUT*1000), self.update)

    def done_updating(self, task_id):
        info('done updating', task_id)
        self.button.set_label("done updating %s" % task_id)


class Updater:
    def __init__(self):
        self._task_id = 0
        self._queue = Queue(maxsize=100) #NOTE: GUI blocks if queue is full
        for _ in range(9):
            t = threading.Thread(target=self._work)
            t.daemon = True
            t.start()

    def _work(self):
        # executed in background thread
        opener = urllib2.build_opener()
        for task_id, done, args in iter(self._queue.get, None):
            info('received task', task_id)
            try: # do something blocking e.g., urlopen()
                data = opener.open('http://localhost:5001').read()
            except IOError:
                pass # ignore errors

            # signal task completion; run done() in the main thread
            GObject.idle_add(done, *((task_id,) + args))

    def add_update(self, callback, *args):
        # executed in the main thread
        self._task_id += 1
        info('sending task ', self._task_id)
        self._queue.put((self._task_id, callback, args))

GObject.threads_init() # init threads?

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()

Gtk.main()

注:GObject.idle_add()異なるスレッドから呼び出される唯一の gtk 関連関数です。

マルチスレッド GTK アプリケーション – パート 1: 誤解も参照してください。

于 2012-08-12T22:14:26.747 に答える
0

スレッド化は、問題を解決する最初の方法です。スレッドを作成し、そのスレッド内で長時間実行されるブロッキング関数を実行できます (GUI はハングアップしません)。

別の方法は、非同期ネットワークを使用することです。たとえば、python-gio (GObject-IO) または GLib のメイン ループで動作する可能性のある別のライブラリを使用します ( Twisted のように)。このアプローチは少し異なり、ノンブロッキング ソケット操作を使用します。ソケット (ポーリングしているサイト) からのデータが読み取れるようになると、メイン ループはコールバックを行います。残念ながら、GIO には高レベルの HTTP API がないため、GSocketClientHTTP リクエスト構造を使用して手動で作成できます。

于 2012-08-12T15:08:45.323 に答える