Home > Software design >  global variable is not changing using _thread
global variable is not changing using _thread

Time:01-21

I use a Raspberry Pi Pico W to control a LED Strip. On the main thread I do all the networking. On the other thread I´m trying to rotate the LED´s in a given interval. However, if I want to change this interval, I have to terminate the thread and create a new thread.

To archive this, I have defined a variable rotate_isAlive, that I want to set to False in order to terminate thread 2 to setup a new one. I use the global keyword for this. This is in my main loop:

global rotate_isAlive
...
if (rotate_isAlive):
    rotate_isAlive = False

if rotation_direction == "right":
    # rotate right
    rotate_isAlive = True
    _thread.start_new_thread(do_rotate_r, (d,ltr)
else:
    # rotate left
    rotate_isAlive = True
    _thread.start_new_thread(do_rotate_l, (d,ltr)

And this is in thread 2:

def do_rotate_l(delay, num_led_to_rotate):
     
while True:
    if rotate_isAlive == False:
        _thread.exit()
        break
    pixels.rotate_left(num_led_to_rotate)
    pixels.show()
    time.sleep(delay/1000)

I followed this guide that suggests the given use of global variables, however my implementation doesn't work: https://www.youtube.com/watch?v=1q0EaTkztIs

CodePudding user response:

Turning what @user2357112 said into a full-on answer:

The very next thing that your main thread does after it sets rotate_isAlive=False is, it sets it back to True again.

if rotate_isAlive:
    if rotate_isAlive = False
if rotation_direction == "right":
    rotate_isAlive = True
    ...
else:
    rotate_isAlive = True
    ...

Meanwhile, the do_rotate thread spends most of its time sleeping. The chance of it fetching rotate_isAlive during the fraction of a microsecond when rotate_isAlive==False is nearly zero.

You need to wait for the do_rotate thread to acknowledge that it saw the flag change. Since it reacts to the flag by dying, you can wait by joining it:

if rotate_isAlive:
    if rotate_isAlive = False
    do_rotate_thread.join()
...

But wait! user2357112 suggested a much better way to solve your problem: Don't kill the thread. Change it's "marching orders."

global g_delay
global g_num_led_to_rotate
global g_rotation_direction

...

g_delay = ...whatever...
g_num_led_to_rotate = ...whatever...
if rotation_direction == "right":
    g_rotation_function = DIR_RIGHT
else:
    g_rotation_function = DIR_LEFT

And in the do_rotate thread:

while True:
    if g_rotation_direction = DIR_RIGHT:
        pixels.rotate_right(g_num_led_to_rotate)
    else:
        pixels.rotate_left(g_num_led_to_rotate)
    pixels.show()
    time.sleep(g_delay/1000)
  • Related