Any harm in idle threads?

now that i have some threading working, i’m building some simple logic and was wondering if leaving a thread to just idle in an if..then loop has any real negative performance cost? to whit, if the check fails, the thread does no work, but continues to check in the event the check succeeds. the expectation is that the thread will run virtually in-perpetuity, restarting only on device power cycle, which ranges from bi-weekly, to quarterly. even as i type this, i think it’s a stupid question, but i can’t leave any stone unturned because i’m new to threading in Python.

If what you mean by “leaving the thread idle in a loop” is anything like this:

while True:
    if some_variable:
        break

Then this is not idling at all, this will consume the full power of your Python application in a certain sense. If you want to make a thread wait on a condition to happen, take a look at threading.Event.

nope. like this:

while True:
    if thing == 'banana':
        # do stuff

the idea being, the thread doesn’t really do anything until the flag is changed. i’ll look @ threading.Event though. but i am curious about the impact of the above.

Still a busy loop. It will continuously check the condition.

1 Like

okay. i thought so. but wanted to confirm. is that not similar to waiting for the event though? same cycles, no? or is that different?

Nope, that’s called busy-waiting.

No, when you wait for an event, there is no loop. One thread will simply call event.wait(), which will block until the event is set. Blocking the waiting thread is what you want: instead of the thread repeatedly asking “are we there yet? what about now?” (which consumes computing power), it will be put to sleep and will be waken up when the event is set. This means that, at some time, in some other thread, you will have to call event.set().

1 Like

ooooh! this is very useful information! thank you! :+1: but it kicks my trike in the ditch because i have to do some rewriting… can i just not work today and have it magically be done? :laughing: off to the docs!! :books:

so, if i am understanding what you said, with my threads, there’s a kind of central-management thread that calls event.set() while my other ‘worker’ threads start with event.wait()… and that management thread can be part of the MQTT on_message callback (which is what handles user interaction) and that kicks off the required threads, yes? if i understand this right, this is actually not that bad.

thank you! :smiley:

presume this is toggle-able behaviour?

It’s not clear to me what exactly you are assuming is togglable.

okay. that’s looks a heck of a lot more elegant than i was anticipating. thank you very much. from what i gleaned, i’ve been tinkering:

import time
import threading
import random

inputSignal = False

def worker_function():
	print(3*f'-----------> working ')

def worker_thread(delay, event):
	#worker.wait()    #<-- this is only good until it enters the loop... duh...
	while True:
	  worker.wait()    #<-- if this is NOT set, it bails right here
	  time.sleep(delay)
	  worker_function()

def manage_function(event):
	print(f'\n||  inside management  ||')
	global inputSignal
	if inputSignal:  #<--toggles the worker thread
		worker.set()
		print(f'=== worker enabled ===')
	else:
		worker.clear()
		print(f'=== worker disabled ===')

def management_thread(delay, event):
	while True:
		time.sleep(delay)
		manage_function(event)


def signalClock(interval):
	while True:
		time.sleep(interval)
		getInputSignal()

def getInputSignal():
	global inputSignal
	inputSignal = True if random.randint(0, 1) else False
	print(f'\n►► inputSignal: {inputSignal} ◄◄\n')
	return inputSignal

worker = threading.Event()

threading.Thread(target=worker_thread, args=(0.25, worker)).start()
threading.Thread(target=management_thread, args=(1.0, worker)).start()
threading.Thread(target=signalClock, args=(0.5,)).start()

while True:    #<-- main application loop
	time.sleep(0.1)
	print(f'main loop')

once the worker thread starts, when the worker.clear() is called, it doesn’t go back to waiting. what am i doing wrong? according to the docs, this should work:

clear()
Reset the internal flag to false. Subsequently, threads calling wait() will block until set() is called to set the internal flag to true again.

EDIT: turns out, i put the worker.wait() outside the loop instead of instead of inside the loop. i corrected the code to reflect this and commented the wrong line for contrast. and, of course, because of the different timings, it will take a few loops to pick up the change.

massive thanks to you guys for your helpful nudges. got me thinking, and thinking in the right direction.