所以我忙着写,需要一定的时间OUF之后,从网站检查更新的应用程序,我使用python的跟Gtk +3
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()运行在主线程。
当用户点击更新按钮,更新()在后台运行。 #thread 2
我想正确的或有我错过了什么?
编辑:好的,
on_update_click功能:
Thread(target=update).start().
K,电脑也不会冻结了:d
那么现在情况是,只有当我关闭Gtk.main()不更新线程才开始。 这是很好的,是继续当UI被关闭更新,但我也喜欢它启动时,用户界面是向上。
于是,我终于设法得到它的工作。 我需要说的:
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解释器中的Gtk主题 !
thread.start_new_thread(update())
是错误的。 它调用update()
立即在主线程和你不应该使用thread
直接模块; 使用threading
模块来代替。
你可以调用threading.current_thread()
来找出哪些线程执行update()
要简化您的代码可以运行在主线程中所有的GTK代码,并使用阻塞操作来检索网页和在后台线程运行。
基于从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部分:误解 。
线程是解决这个问题的第一种方式。 您可以创建线程和运行长期运行阻塞线程内部功能(和你的GUI不会挂断电话)。
另一种方法是使用python-GIO(GObject的-IO),或有可能与GLib的主回路工作(另一个库使用异步联网比如像他们这样做与扭曲 )。 这种做法有点不同,并使用非阻塞套接字操作。 你的主循环,可以使一个回调时,从套接字数据(网站你轮询)将可阅读。 不幸的是GIO没有高层次的HTTP API,所以你可以使用GSocketClient
和手动创建HTTP请求结构。