【问题标题】:Run dependent threads simultaneously in Python在 Python 中同时运行依赖线程
【发布时间】:2020-02-13 09:11:02
【问题描述】:

我有两个线程类提取和检测。

Extract 从视频中提取帧并将其存储在文件夹中,Detect 从提取帧的文件夹中获取图像并检测对象。

但是当我运行下面的代码时,只有提取有效:

global q
q = Queue()

class extract(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print("T1")
        cam = cv2.VideoCapture(video_name)
        frameNum = 0
        # isCaptured = True
        frameCount = 0
        while True:
            isCapture, frame = cam.read()
            if not isCapture:
                break
            if frameCount % 5 == 0:
                frameNum = frameNum + 1
                fileName = vid + str(frameNum) + '.jpg'
                cv2.imwrite('images/extracted/' + fileName, frame)
                q.put(fileName)
            frameCount += 1
        cam.release()
        cv2.destroyAllWindows()

class detect(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print("T2")
        #logic to detect objects. 


if __name__ == '__main__':
    thread1 = extract()
    thread1.start()
    thread2 = detect()
    thread2.start()

这只会打印 T1 而不会打印 T2。 我想可能检测到先运行,队列是空的,所以什么也没发生,所以我在队列中添加了虚拟条目,它按照我想要的方式运行。

但它只针对虚拟条目运行,它不适用于提取函数添加到队列中的条目。 查找了其他问题,但似乎都没有解决问题,因此在此处发布此问题

【问题讨论】:

  • 您对detect 的工作基本上是在extract 完成工作之后开始的。那你为什么要它们并行运行
  • 我正在进行实时检测,这就是为什么我需要它们一起运行

标签: python python-3.x multithreading python-multithreading


【解决方案1】:

您可能还希望将检测逻辑保持在无限循环中。

class detect(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while True: 
        #detect frame

如果是单帧检测。 然后考虑在检测线程中等待。

from time import sleep
class detect(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)

        def run(self):
           sleep(120)
           # Detect logic

【讨论】:

  • 这仍然给出相同的输出
【解决方案2】:

您可以使用Event() 并让您的检测线程等到设置Event() 后再执行检测,而不是等待硬编码时间

如果设置了事件,则意味着所有任务都已完成。此外,如果有任何任务尚未处理,您还必须密切关注队列。

我已经编写了一个示例代码来演示它是如何工作的,您可以根据需要修改代码。

这里extract 需要 5 秒来将任务添加到队列中,detect 每 1 秒检查一次任务。因此,如果提取的速度比任何可用的东西都慢,那么detect 将处理它。当所有任务都完成后,检测会跳出循环。

import threading
import queue
import time

global q
q = queue.Queue()

class extract(threading.Thread):
    all_tasks_done = threading.Event()
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        counter = 5
        while counter:
            time.sleep(5)
            counter -= 1
            q.put(1)
            print("added a task to queue")
        extract.all_tasks_done.set()



class detect(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while not extract.all_tasks_done.wait(1) or not q.empty():
            print(q.get())
        print("detection done")
        #logic to detect objects. 


if __name__ == '__main__':
    thread1 = extract()
    thread1.start()
    thread2 = detect()
    thread2.start()
    thread1.join()
    thread2.join()
    print("work done")

【讨论】:

  • 在 run 的 while 循环中。运行这个脚本一次,看看它是否像你期望的那样工作,提取和检测工作
  • 不,这并没有给我预期的输出。我使用 rabbitmq 从提取中传递消息并在检测中检索它。完成了这项工作
猜你喜欢
  • 2022-06-24
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多