我目前正在使用python(2.7)编写一个有一些线程的GUI。我遇到了一个问题,我需要在获取一条信息之前做大约大约一秒钟的延迟,但我不能让这个函数花费超过几毫秒来运行。考虑到这一点,我正在尝试创建一个Threaded计时器,它将设置一个标志timer.doneFlag
并具有主要功能,以便继续查看它是否已完成。
它正在发挥作用。但不是所有的时间。我遇到的问题是,有时我感觉像time.sleep
中的run
函数,不会等待一秒钟(有时甚至可能不等待)。我需要的是我可以有一个标志,允许我控制开始时间并在达到1秒时抬起标志。
我可能做的太多只是为了得到一个可线程的延迟,如果你可以提出建议,或者帮助我在下面的代码中找到一个bug,我将非常感激!
我附上了我使用的部分代码:
来自主程序:
class dataCollection:
def __init__(self):
self.timer=Timer(5)
self.isTimerStarted=0
return
def StateFunction(self): #Try to finish the function within a few milliseconds
if self.isTimerStarted==0:
self.timer=Timer(1.0)
self.timer.start()
self.isTimerStarted=1
if self.timer.doneFlag:
self.timer.doneFlag=0
self.isTimerStarted=0
#and all the other code
import time
import threading
class Timer(threading.Thread):
def __init__(self, seconds):
self.runTime = seconds
self.doneFlag=0
threading.Thread.__init__(self)
def run(self):
time.sleep(self.runTime)
self.doneFlag=1
print "Buzzzz"
x=dataCollection()
while 1:
x.StateFunction()
time.sleep(0.1)
答案 0 :(得分:0)
首先,您已经有效地重建了threading.Timer
,但灵活性较低。所以我认为你最好使用现有的课程。 (为每个计时器实例创建一个线程有一些明显的缺点。但如果你只想要一个单次计时器,那很好。)
更重要的是,让主线程重复轮询doneFlag
可能是一个坏主意。这意味着你必须尽可能多地调用你的状态函数,没有充分理由燃烧CPU。
大概你必须在几毫秒内返回的原因是你正在返回某种事件循环,大概是你的GUI(但是,例如,网络反应堆有相同的问题,使用相同的解决方案,所以我会保持一般性。)
如果是这样,几乎所有这样的事件循环都有办法在事件循环中安排定时回调 - Timer
中的wx
,callLater
中的twisted
等。所以,使用它。
如果您使用的框架没有类似的东西,那么希望至少有一些方法可以发送一个事件/触发信号/发布消息/从外部调用它。 (如果它是一个简单的基于文件描述符的反应堆,它可能没有那个,但你可以通过将一个管道扔进反应堆来自己添加它。)所以,改变你的Timer
回调来指示事件循环,而不是编写轮询Timer
的代码。
如果由于某种原因你真的做需要轮询在线程之间共享的变量,那么你真的应该用Condition
或RLock
来保护它。在语言中无法保证,当线程0更新值时,线程1将立即看到新值,甚至永远。如果您了解CPython(特定版本)的内部结构,您通常可以证明GIL在特定情况下不需要锁定。但除此之外,这是一场比赛。
最后:
我遇到的问题是,有时我觉得运行中的time.sleep函数,不会等待一秒钟(有时甚至可能不等待)。
嗯,the documentation明确表示会发生这种情况:
实际暂停时间可能小于请求的时间,因为任何捕获的信号将在执行该信号的捕获程序后终止sleep()。
所以,如果你需要保证它实际上至少睡了1秒钟,那么这样做的唯一方法就是这样:
t0 = time.time()
dur = 1.0
while True:
time.sleep(dur)
t1 = time.time()
dur = 1.0 - (t1 - t0)
if dur <= 0:
break