Douwe Douwe - 3 months ago 9
Python Question

Non-blocking way to determine if thread is finished?

I have the following code:

import threading
import time

class TestWorker (threading.Thread):
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name

def run(self):
print "Starting " + self.name
time.sleep(20)
print "Exiting " + self.name
# how do I let the calling thread know it's done?

class TestMain:
def __init__(self):
pass

def do_work(self):
thread = TestWorker(1, "Thread-1")
thread.start()

def do_something_else(self):
print "Something else"

def on_work_done(self):
print "work done"


How can I let the main thread know that the
TestWorker
has finished (call
on_work_done()
), without blocking calls to
do_something_else()
as
thread.join()
would?

Answer

You can give your thread instance an optional callback function to call when it's finished.
Note I added a Lock to prevent concurrent printing (which does block).

import threading
import time

print_lock = threading.Lock()  # prevent threads from printing at same time

class TestWorker(threading.Thread):
    def __init__(self, threadID, name, callback=None):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.callback = callback if callback else lambda: None

    def run(self):
        with print_lock:
            print("Starting " + self.name)
        time.sleep(3)
        with print_lock:
            print("Exiting " + self.name)
        self.callback()

class TestMain:
    def __init__(self):
        self.work_done = False

    def do_work(self):
        thread = TestWorker(1, "Thread-1", self.on_work_done)
        thread.start()

    def do_something_else(self):
        with print_lock:
            print("Something else")

    def on_work_done(self):
        with print_lock:
            print("work done")
        self.work_done = True

main = TestMain()
main.do_work()
while not main.work_done:
    main.do_something_else()
    time.sleep(.5)  # do other stuff...

print('Done')

Output:

Starting Thread-1
Something else
Something else
Something else
Something else
Something else
Something else
Exiting Thread-1
Something else
work done
Done
Comments