Python 多处理自更新对象

问题描述 投票:0回答:1

我正在尝试编写一个基本方向的显示。我有一个以高刷新率运行的界面,以及一个每秒仅更新几次的硬件设备。

每次显示器更新时,我需要能够从硬件获取最新的报告值到显示器。

我目前的方法是尝试多处理。我有一个进程通过共享状态管道获取值并使用这些值更新对象,并且我有一个进程从对象中获取值并更新显示。

不幸的是,它似乎在某个地方被阻塞,并且显示被锁定到硬件更新速度。

class AccMag():
    # Init manually to ensure access to and for internal functions
    def init(self):
        # This defines the hardware access
        self.i2c = busio.I2C(board.SCL, board.SDA)
        self.mag = adafruit_lis2mdl.LIS2MDL(self.i2c)
        self.accel = adafruit_lsm303_accel.LSM303_Accel(self.i2c)

        # Output values (mag#) and pipes to the other process
        self.magx = 0
        self.pipex = multiprocessing.Value('d', 0.0)
        self.magy = 0
        self.pipey = multiprocessing.Value('d', 0.0)
        self.magz = 0
        self.pipez = multiprocessing.Value('d', 0.0)

        # The process, named thread.  Yes, my cat is named Rex.
        self.thread = multiprocessing.Process(target=self.threadmagdate, args=(self.pipex, self.pipey, self.pipez))
        self.thread.start()

        # A counter I use to see how often the process has run.
        # Comparing this counter to a similar one in the display is how I know it's blocking.
        self.tc = 0

    # The function that starts the process to update the values
    def magdate(self):
        # Check the current process is done
        self.thread.join(timeout=0)
        if self.thread.is_alive() == False:
            # Pull out previous values
            self.magx = self.pipex.value
            self.magy = self.pipey.value
            self.magz = self.pipez.value
            self.tc += 1
            # Start a new process
            self.thread = multiprocessing.Process(target=self.threadmagdate, args=(self.pipex, self.pipey, self.pipez))
            self.thread.start()

    # Get the data from the hardware into the pipe
    def threadmagdate(self, magx, magy, magz,):
        magx.value = int(self.mag.magnetic[1])
        magy.value = int(self.mag.magnetic[0])
        magz.value = int(self.mag.magnetic[2])

然后显示器可以调用 magdate() 并从 mag# 值中获取值。

我遗漏了一些明显的东西,我可以闻到它的味道,但我不知道为什么它会锁定。

python multiprocessing python-multithreading
1个回答
0
投票

self.thread.join(timeout=0)
似乎是毫无意义的代码行,因为
join()
通常用于等待进程完成一段时间,但在这种情况下,它实际上根本不等待。

根据您的代码,我没有看到任何可能阻塞的内容,但是在某些平台上,启动新进程可能需要一段时间(有时超过1秒)取决于进程启动方法

鉴于

magdate()
每次被调用时都可能启动一个新进程,我怀疑这就是“阻塞”发生的地方。

因此,我建议不要每次在

magdate()
中启动一个新进程,而是使用
Queue
对象。

from multiprocessing import Queue, Process, Event

class AccMag():
    # Init manually to ensure access to and for internal functions
    def init(self):
        # This defines the hardware access
        self.i2c = busio.I2C(board.SCL, board.SDA)
        self.mag = adafruit_lis2mdl.LIS2MDL(self.i2c)
        self.accel = adafruit_lsm303_accel.LSM303_Accel(self.i2c)

        # Set up queue and a termination event
        self.queue = Queue()
        self.terminate_event = Event()

        # The process, named thread.  Yes, my cat is named Rex.
        self.thread = Process(target=self.threadmagdate, args=(self.queue, self.terminate_event))
        self.thread.start()

        # A counter I use to see how often the process has run.
        # Comparing this counter to a similar one in the display is how I know it's blocking.
        self.tc = 0

    def stop(self):
        self.terminate_event.set()  ## trigger termination event
        self.thread.join()  ## wait for process to terminate

    # The function that starts the process to update the values
    def magdate(self):
        # Check if new value is available
        if not self.queue.empty():
            x, y, z = self.queue.get()

            # Pull out new values
            self.magx = int(x)
            self.magy = int(y)
            self.magz = int(z)

            self.tc += 1

    # Get the data from the hardware into the pipe
    def threadmagdate(self, queue, terminate_event):
        while not terminate_event.is_set():  ## check if it's time to stop reading values
            queue.put(self.mag.magnetic)  ## insert new reading into queue
© www.soinside.com 2019 - 2024. All rights reserved.