embedded.95
embedded.95

Reputation: 63

How can I create non-blocking threads?

I have been trying to use Threads in python. I am working on a Pi hardware project.

Here's the problem:

When I create a thread, and call it like this, the loop keeps creating new threads before the old ones are completed. Hence, slowing the program down... (printing 'threading.active_count' displays 20+ active threads).

while True:
    t4 = Thread(target = myFunc, args=())
    t4.start()

    print("Hello World")

I need a threading process that runs the same function over and over on a SINGLE thread without affecting or delaying my main program. i.e. when a thread has completed executing the function, run it again... but my main should still be printing "Hello World" as normal.

I've found one way to stop it crashing, which is to sit and "wait" until the thread is finished, and then start again. However, this is a blocking approach, and completely defeats the purpose of threading.

while True:
    t4 = Thread(target = myFunc, args=())
    t4.start()
    t4.join()

    print("Hello World")

Any suggestions?

Upvotes: 1

Views: 5482

Answers (4)

martineau
martineau

Reputation: 123393

You can use a multiprocessing.pool.ThreadPool to manage both the starting of new threads and limiting the maximum number of them executing concurrently.

from multiprocessing.pool import ThreadPool
from random import randint
import threading
import time

MAX_THREADS = 5  # Number of threads that can run concurrently.
print_lock = threading.Lock()  # Prevent overlapped printing from threads.

def myFunc():
    time.sleep(random.uniform(0, 1))  # Pause a variable amount of time.
    with print_lock:
        print('myFunc')

def test():
    pool = ThreadPool(processes=MAX_THREADS)

    for _ in range(100):  # Submit as many tasks as desired.
        pool.apply_async(myFunc, args=())

    pool.close()  # Done adding tasks.
    pool.join()  # Wait for all tasks to complete.
    print('done')


if __name__ == '__main__':
    test()

Upvotes: 4

Solomon Slow
Solomon Slow

Reputation: 27115

I need a threading process that runs the same function over and over on a SINGLE thread

This snippet creates a single thread that continually calls myFunc().

def threadMain() : 
    while True :
        myFunc()

t4 = Thread(target = threadMain, args=())
t4.start()

Upvotes: 1

zwer
zwer

Reputation: 25769

Make a delegate thread - i.e. a thread to run your other threads in sequence:

def delegate(*args):
    while True:
        t = Thread(target=myFunc, args=args) # or just call myFunc(*args) instead of a thread
        t.start()
        t.join()

t = Thread(target=delegate, args=())
t.start()
while True:
    print("Hello world!")

Or even better, redesign your myFunc() to run its logic within a while True: ... loop and start the thread only once.

I'd also advise you to add some sort of a delay (e.g. time.sleep()) if you're not performing any work in your threads to help with context switching.

Upvotes: 1

kgr
kgr

Reputation: 789

setDaemon(True) from threading.Thread class more here https://docs.python.org/2/library/threading.html#threading.Thread.daemon

Upvotes: 0

Related Questions