Run dependent threads simultaneously in Python

守給你的承諾、 提交于 2020-07-10 03:38:28

问题


I have two thread classes extract and detect.

Extract extracts frames from a video and stores it in a folder, Detect takes images from the folder where frames are extracted and detects objects.

But when I run the below code only the extract works:

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()

This prints only T1 and no T2. I thought probably detect ran first and queue was empty so nothing happened so I added dummy entries into the queue and it ran how I wanted it to.

But it ran only for the dummy entries, it didn't work for the entries that the extract function added to the queue. Looked up other questions and none of them seemed to solve the problem, hence posting this here


回答1:


You probably want to keep your detect logic in infinite loop as well.

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

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

And if it is a single frame detection. Then consider waiting in detect thread.

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

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



回答2:


Instead of waiting for a hardcoded time you can make use of Event() and make your detect thread wait until the Event() is set before performing the detection

If the event is set that means all tasks are done. Additionally, you also have to keep an eye on the queue if any tasks are there yet not processed.

I have written an example code to demonstrate how it works you can modify the code according to your needs.

Here extract takes 5 seconds to add a task to queue and detect checks for a task every 1 second. So if the extract is slower than also whenever something is available is will be processed by detect. And when all tasks are done detect will break out of the loop.

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")


来源:https://stackoverflow.com/questions/60204098/run-dependent-threads-simultaneously-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!