python2.7中的线程延迟

2024-10-03 11:18:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在使用python(2.7)编写一个GUI,其中包含一些线程。我遇到了一个问题,在获取信息之前,我需要做大约一秒钟的延迟,但是我不能让函数运行超过几毫秒。考虑到这一点,我尝试创建一个线程计时器,它将设置一个标志timer.doneFlag,并具有main函数来持续检查是否完成。在

它正在工作。但不是一直这样。我遇到的问题是,有时我觉得run中的time.sleep函数没有完全等待一秒钟(有时甚至可能不等待)。当旗子到达我需要的时候,我就可以举起旗子。在

我可能做了太多的事情只是为了得到一个可线程化的延迟,如果你能提出一些建议,或者帮助我在下面的代码中找到一个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)

Tags: 函数run代码selftimeinitdefsleep
1条回答
网友
1楼 · 发布于 2024-10-03 11:18:06

首先,您有效地重建了^{},但灵活性较差。所以我认为你最好使用现有的类。(为每个计时器实例创建线程有一些明显的缺点。但如果你只想要一个一次性计时器,那就好了。)

更重要的是,让主线程反复轮询doneFlag可能是个坏主意。这意味着你必须尽可能频繁地调用你的状态函数,无缘无故地消耗CPU。在

你必须在几毫秒内返回的原因大概是你正在返回某种事件循环,大概是为了你的GUI(但是,例如,一个网络反应器有相同的问题,有相同的解决方案,所以我将保持一般性)。在

如果是这样的话,几乎所有这样的事件循环都有一种方法来安排事件循环中的定时回调-Timerwxtwisted中的callLater,等等。所以,使用这个方法。在

如果你使用的是一个没有这样东西的框架,它至少有一些方法可以发送事件/发出信号/发布消息/无论它是从外部调用的。(如果它是一个简单的基于文件描述符的reactor,它可能没有,但是您可以自己添加它,只需将一个管道放入reactor中即可。)因此,更改Timer回调以通知事件循环,而不是编写轮询Timer的代码。在

如果出于某种原因,您确实需要轮询跨线程共享的变量,那么您应该使用Condition或{}来保护它。语言中不能保证,当线程0更新值时,线程1将立即看到新值,甚至是永远。如果您对CPython(特定版本)的内部结构有足够的了解,您通常可以证明GIL在特定情况下不需要锁。但不然,这是一场比赛。在

最后:

The problem that I run into is that sometimes I feel like the time.sleep function in run , doesn't wait fully for a second (sometimes it may not even wait).

嗯,the documentation清楚地表明这是可能发生的:

The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine.

所以,如果你需要保证它至少能睡1秒钟,唯一的办法就是这样:

t0 = time.time()
dur = 1.0
while True:
    time.sleep(dur)
    t1 = time.time()
    dur = 1.0 - (t1 - t0)
    if dur <= 0:
        break

相关问题 更多 >