0

So I'm doing some testing with threads and I realised I could not stop and then start a thread. I could stop it, but starting it again was the issue.

I want a script that adds 1 to a var when it is on then its stops when off by pressing shift to turn on and off.
I have the detecting shift working (it is on another part of my code), but I just need to find out how to stop and start threads

Here is my test code:

from threading import Thread as th
import time as t
var = 0
def testDef():
    global var
    var += 1:
    t.sleep(1)
test = th(target = testDef)
test.start()
while True:
    menu = input("On, Off, Show Var")
    if menu == "On":
        test.start()
    elif menu == "Off":
        test._stop():
    elif menu == "S":
        print(var)

I know there are a few errors, but I mainly need the on and off threading to work. Thanks, Jeff.

Jeff
  • 1
  • 1

4 Answers4

1

As far as I know, you can't actually stop and restart a thread as you can't use test.start() when the method has been terminated. However, you may be wondering to something similar by using threading.Condition to pause and later resume the execution.

You can read more about it in the documentation.

There is also an error in var += 1:, change it to var += 1

Gerard Vives
  • 57
  • 10
0

Here's a simple example on how to use threading.Event to enable two threads to communicate. This works by setting the internal flag of the Event to either True or False. While this internal flag is False you can ask thread a to wait (effectively block, which is not very efficient by the way). Then we use the two timers (b, c) to simulate a shift press every 5 seconds. In order to release a we set the event (internal flag = True). 5 seconds later, we clear the value of the internal flag and this will make thread a to block again.

import threading

def do(event):
    flag = True
    while flag:
        if not event.isSet():
            print "blocking"
            event.wait()
        else:
            print "resuming"


def pressShift(event, enable):
    print "Shift pressed"
    if enable:
        event.set()
    else:
        event.clear()

def main():
    event = threading.Event()
    a = threading.Thread(target=do, args=(event,))
    b = threading.Timer(5, pressShift, args=(event, True)).start()
    c = threading.Timer(10, pressShift, args=(event, False)).start()
    a.start()
    a.join()

if __name__ == "__main__":
    main()
paperino9
  • 159
  • 1
  • 8
  • Thanks for the reply Thomas, but it seems that when I press shift its resumes but i have to press shift many times for it to recognise the shift again and go back to blocking. Any fixes? – Jeff Aug 18 '18 at 19:28
0

You cannot restart a thread that has already been started. What you can do, however, is to create another thread.

from threading import Thread as th
import time as t
var = 0
def testDef():
    global var
    var += 1
    t.sleep(1)
test = th(target = testDef)
test.start()
while True:
    menu = input("On, Off, Show Var")
    if menu == "On":
        test = th(target = testDef)
        test.start()
    elif menu == "Off":
        test._stop()
    elif menu == "S":
        print(var)
brandonwang
  • 1,603
  • 10
  • 17
  • Thanks for the reply, It seems that the variable is not increasing and the variable increases by 1 when you enter "On" but not any more after that unless you enter "On" again. Any reasons? – Jeff Aug 18 '18 at 19:36
0

Use an event object like this post, and check that event in your target functoin. Also, you need a new thread each time you re-start. The code shown below adds some debugging that should be useful. (Another approach is to build a custom stop function.)

import logging
import threading
import time as t
var = 0

logging.basicConfig(level=logging.DEBUG,
                    format='[%(levelname)s] (%(threadName)-10s) %(message)s',
                    )

def testDef(stop_event):
    global var
    print 'Thread Running', var
    # inThread.stop()
    while not stop_event.isSet():
        var += 1
        logging.debug('Var is %i' % var) 
        t.sleep(1)

# Use an event to track user input
testStopEvent = threading.Event()
testStopEvent.clear()

test = threading.Thread(name = 'test', target=testDef, args=((testStopEvent,)))
test.setDaemon(True)
while True:
    menu = input("On = 1, Off = 2, Show Var = 3")
    if menu == 1:
        test.start()
    elif menu == 2:
        testStopEvent.set()
        test.join() # Wait for the thread to finish
        test = threading.Thread(target=testDef, args=((testStopEvent,))) # "re-start" thread
        testStopEvent.clear() # Reset the stop event

    elif menu == 3:
        print(var)