SO的新手,请原谅任何礼节错误(指出是否有!)。
我正在处理在程序主UI线程上运行的脚本。话虽这么说,我需要避免所有阻止调用,以确保用户仍然可以进行交互。我无法访问UI事件循环,因此在我的情况下,任何繁忙的循环解决方案都是不可能的。
我有一个简单的后台线程,它正在与另一个应用程序通信并收集数据,并存储在一个简单的数组中以供使用。每次更新此数据时,我都需要使用数据来修改UI(这必须在主线程中运行)。理想情况下,后台线程每次更新数据时都会发出一个信号,然后在主线程中,侦听器会处理这个并修改UI。繁忙的循环不是一个选项,一切都必须基于异步/事件。
我使用threading.timer(..)在后台继续运行数据收集。但是,由于这是在一个单独的线程中运行,因此需要在外部调用UI操作。
def _pollLoop(self):
if (self._isCubeControl):
self._getNewData()
#in a perfect world, updateUI() would be here
self._pollThread = threading.Timer(0.1,self._pollLoop)
self._pollThread.start()
我需要一种方法让这个pollLoop回调到主线程,这样我就可以更新UI了。我在pollLoop中尝试过直接回调,但回调是在单独的线程中运行导致错误。
寻找一种方法将侦听器附加到数据对象,以便在更改时可以在主线程中运行updateUI()。
感谢您提供的任何帮助!如果这很模糊,请告诉我
根据@ CAB的答案,我现在正试图实施观察员模式。难点在于Observable将在生成的线程中运行,而Observer更新函数必须在主线程中运行。我已经实施了示例chad lung(http://www.giantflyingsaucer.com/blog/?p=5117)。
import threading
class Observable(object):
def __init__(self):
self.observers = []
def register(self, observer):
if not observer in self.observers:
self.observers.append(observer)
def unregister(self, observer):
if observer in self.observers:
self.observers.remove(observer)
def unregister_all(self):
if self.observers:
del self.observers[:]
def update_observers(self, *args, **kwargs):
for observer in self.observers:
observer.update(*args, **kwargs)
thread = threading.Timer(4,self.update_observers).start()
from abc import ABCMeta, abstractmethod
class Observer(object):
__metaclass__ = ABCMeta
@abstractmethod
def update(self, *args, **kwargs):
pass
class myObserver(Observer):
def update(self, *args, **kwargs):
'''update is called in the source thread context'''
print(str(threading.current_thread()))
observable = Observable()
observer = myObserver()
observable.register(observer)
observable.update_observers('Market Rally', something='Hello World')
我得到的回应是:
<_MainThread(MainThread, started 140735179829248)>
<_Timer(Thread-1, started 123145306509312)>
<_Timer(Thread-2, started 123145310715904)>
显然Observer正在生成的线程中运行而不是main。有人对我有另一种方法吗? :)再一次,我不能有一个繁忙的循环来定期检查值的变化(我希望.. :()这个脚本运行超过UI,我无法访问GUI事件循环,所以一切都需要异步和非阻塞。
答案 0 :(得分:2)
让我们从http://www.giantflyingsaucer.com/blog/?p=5117开始构建该示例。
from abc import ABCMeta, abstractmethod
class Observer(object):
__metaclass__ = ABCMeta
@abstractmethod
def update(self, *args, **kwargs):
pass
然后,在Observer实现上有责任断开线程。让我们说我们使用一个简单的线程来做到这一点。 (语法可能已关闭,我正在填写此内容并需要捕获总线)。
from observer import Observer
from threading import Thread
class myObserver(Observer):
def update(self, *args, **kwargs):
'''update is called in the source thread context'''
Thread(target=self.handler, args=(self,*args), kwargs=**kwargs).start()
def handler(self, *args, **kwargs):
'''handler runs in an independent thread context'''
pass # do something useful with the args