【问题标题】:What's the best method to create a thread that can be ended from the main thread in python?创建可以从python中的主线程结束的线程的最佳方法是什么?
【发布时间】:2013-04-05 02:31:36
【问题描述】:

我正在从加速度计捕获数据。我希望用户能够通过分别按下开始和停止按钮来开始记录数据和停止记录。我决定使用线程来执行此操作,因此开始按钮会创建一个捕获数据的线程,而停止按钮会停止该线程并获取记录的数据。

我遇到的问题是,要么没有记录数据,要么按下停止按钮时,线程没有结束,而是继续记录数据,时间从几秒钟到几分钟不等。

我现在正在做的是线程运行一个循环来记录数据并检查变量是否设置为 True,如果是,则循环应该结束。我还有一个 end() 函数,该函数旨在从主线程调用,并假设将变量设置为 True 以结束线程。

class Capture(Thread):
def __init__(self,accel):
    Thread.__init__(self)
    self.accel=accel
    self.ended=False
    self.data=[]
    self.lock=Lock()

def run(self):
    while self.isEnded()==False:
        self.lock.acquire()
        self.data.append(self.accel.read())
        self.lock.release()

def getData(self):
    self.lock.acquire()
    d=self.data
    self.data=[]
    self.lock.release()
    return d

def isEnded(self):
    self.lock.acquire()
    end=self.ended
    self.lock.release()
    return end

def end(self):
    self.lock.acquire()
    self.ended=True
    self.lock.release()

【问题讨论】:

  • 可以self.accel.read() 阻塞几分钟吗?您是否尝试过:data = self.accel.read() \n with lock: self.data.append(data) 以避免长时间阻塞 getData()。或者读取较小的块直到记录分隔符?或者只使用 Queue.get_nowait() 而不使用显式锁定。你不需要锁定self.ended。如果你需要在另一个线程中等待isEnded();你可以使用threading.Event.wait()。您可能根本不需要线程来读取文件而不阻塞 GUI,例如 GObject.io_add_watch
  • self.accel.read() 无法阻塞几分钟,超时设置为一秒。问题不在于 getData() 被阻塞,而是当我调用 end() 时,线程要么立即结束,但不产生数据,要么继续以正常速度运行 5 秒到几分钟。当我调用 thread.end() 时,该块进入主线程。
  • 你试过改变了吗?

标签: python multithreading python-multithreading


【解决方案1】:

恐怕我对python不太了解,但我会猜测一下。如果 accel.read() 调用一些外部代码(例如设备驱动程序)并阻塞一秒钟,那么 python 解释器也会被阻塞。没有其他线程将运行。当读取最终返回时,您释放锁。此时,解释器将不得不决定下一步该做什么,而您的线程只是循环,再次获取锁并返回读取(并被阻塞)

所以我猜你遇到了解释器锁,并且你的主线程是否运行有一个盲目的运气因素,在这种情况下你的停止按钮处理不会发生。

可以吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多