Stopping a Thread with Time Slicing

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steve

    Stopping a Thread with Time Slicing

    Hi All,

    I've been trying to come up with a good way to run a certain process
    at a timed interval (say every 5 mins) using the SLEEP command and a
    semaphore flag. The basic thread loop was always sitting in the sleep
    command and not able to be interrupted. When the time came to set the
    semaphore flag to false (stopping the thread), my program would have
    to wait up to the entire sleep time to break out of the loop.

    I have finally found a very workable solution to break out of the
    sleep loop by using a time slicing loop to divide the overall sleep
    time into small pieces (slices) giving the loop more opportunities to
    be interrupted.


    Here is my code :

    -------------------------------------------------------------

    import time
    import datetime
    import threading


    def log(message):

    now = datetime.dateti me.now().strfti me("%H:%M:%S")
    print "%s : %s" % (now, message)



    class StoppableThread (threading.Thre ad):

    def __init__(self, sleep_time, time_slice):

    self.sleep_time = sleep_time
    self.running = True
    self.time_slice = time_slice

    threading.Threa d.__init__(self )


    def run(self):

    while self.running:

    log('Thread Running...')
    #process_some_d ata() ## <<-- Call some def here to perform
    some timed task
    log('## Do Some Work Here ##\n')

    # Sleep Loop :
    # Put sleeps in time_slice loop, with sleep = sleep_time /
    time_slice
    # This gives the sleep loop more opportunities to be interrupted
    # when the running flag is set to False

    for current_loop in range(0, self.time_slice ) :

    time.sleep(self .sleep_time / self.time_slice )

    if not self.running: # check the flag
    break # break out of the sleep loop


    log('** Thread Has STOPPED!')


    def stop(self): # stop the thread from running
    self.running = False


    ############### ############### ############### ############### #########
    # T E S T
    ############### ############### ############### ############### #########

    SMALL_SLEEP = 35
    CHECK_SLEEP = 300 # sleep interval in seconds to run a timed
    process
    TIME_SLICE = 100 # number of slices to divide CHECK_TIME
    (higher number = faster kill response)


    log('Create Thread')
    thread_obj = StoppableThread (CHECK_SLEEP, TIME_SLICE)

    log('Thread Start\n')
    thread_obj.star t()

    for current_loop in range(0,10):
    time.sleep(SMAL L_SLEEP)
    log('current loop = %d \n' % current_loop)

    log('Thread Stop')
    thread_obj.stop ()

    log('Done!')


    --------------------------------------------

    Test Results :
    >python Simple_Thread.p y
    15:37:23 : Create Thread
    15:37:23 : Thread Start

    15:37:23 : Thread Running...
    15:37:23 : ## Do Some Work Here ##

    15:37:58 : current loop = 0

    15:38:33 : current loop = 1

    15:39:08 : current loop = 2

    15:39:43 : current loop = 3

    15:40:18 : current loop = 4

    15:40:53 : current loop = 5

    15:41:28 : current loop = 6

    15:42:03 : current loop = 7

    15:42:23 : Thread Running...
    15:42:23 : ## Do Some Work Here ##

    15:42:38 : current loop = 8

    15:43:13 : current loop = 9

    15:43:13 : Thread Stop
    15:43:13 : Done!
    15:43:14 : ** Thread Has STOPPED!
  • Todd Whiteman

    #2
    Re: Stopping a Thread with Time Slicing

    Steve wrote:
    Hi All,
    >
    I've been trying to come up with a good way to run a certain process
    at a timed interval (say every 5 mins) using the SLEEP command and a
    semaphore flag. The basic thread loop was always sitting in the sleep
    command and not able to be interrupted. When the time came to set the
    semaphore flag to false (stopping the thread), my program would have
    to wait up to the entire sleep time to break out of the loop.
    >
    I have finally found a very workable solution to break out of the
    sleep loop by using a time slicing loop to divide the overall sleep
    time into small pieces (slices) giving the loop more opportunities to
    be interrupted.
    A better approach for this is to use a Python Event or Condition object:
    Source code: Lib/threading.py This module constructs higher-level threading interfaces on top of the lower level_thread module. Availability: not WASI. This module does not work or is not available...


    Example code:


    import threading
    my_stop_event = threading.Event ()

    # Sleep Loop :
    #for current_loop in range(0, self.time_slice ) :
    # time.sleep(self .sleep_time / self.time_slice )

    event.wait(self .sleep_time)
    if not self.running: # check the flag
    break # break out of the sleep loop

    # From another thread, you can notify the above sleeping thread using:
    my_stop_event.s et()


    Cheers,
    Todd

    Comment

    • Steve

      #3
      Re: Stopping a Thread with Time Slicing

      Hi Todd,

      Thanks for your suggestions on using the Event condition methods on
      this thread.

      Here is my updated code :


      import time
      import datetime
      import threading


      def log(message):

      now = datetime.dateti me.now().strfti me("%H:%M:%S")
      print "%s : %s" % (now, message)



      class StoppableThread (threading.Thre ad):

      def __init__(self, sleep_time, function, args=[], kwargs={}):

      self.sleep_time = sleep_time

      threading.Threa d.__init__(self )

      self.function = function
      self.args = args
      self.kwargs = kwargs
      self.finished = threading.Event ()


      def run(self):

      while not self.finished.i sSet(): # loop while condition
      is true
      log('** Doing Work')
      self.function(* self.args, **self.kwargs) # run the function
      self.finished.w ait(self.sleep_ time) # put thread in wait
      state


      log('** Thread Has STOPPED!')


      def stop(self): # stop the thread from running
      log('* Stopping Thread')
      self.finished.s et()
      self.join()




      def my_function (a, b, c):
      log('my_functio n running... %s' % a)


      ############### ############### ############### ############### #########
      # T E S T
      ############### ############### ############### ############### #########

      SMALL_SLEEP = 35
      CHECK_SLEEP = 300 # sleep interval in seconds to run a timed
      process


      log('Create Thread')
      thread_obj = StoppableThread (CHECK_SLEEP, my_function, (15,0,-1))


      log('Thread Start\n')
      thread_obj.star t()

      for current_loop in range(0,10):
      time.sleep(SMAL L_SLEEP)
      log('current loop = %d \n' % current_loop)

      log('Call Thread Stop')
      thread_obj.stop ()

      log('Done!')


      Test Output :
      >python Simple_Thread_S top_Event.py
      12:58:42 : Create Thread
      12:58:42 : Thread Start

      12:58:42 : ** Doing Work
      12:58:42 : my_function running... 15
      12:59:17 : current loop = 0
      12:59:52 : current loop = 1
      13:00:27 : current loop = 2
      13:01:02 : current loop = 3
      13:01:37 : current loop = 4
      13:02:12 : current loop = 5
      13:02:47 : current loop = 6
      13:03:22 : current loop = 7
      13:03:42 : ** Doing Work
      13:03:42 : my_function running... 15
      13:03:57 : current loop = 8

      13:04:32 : current loop = 9

      13:04:32 : Call Thread Stop
      13:04:32 : * Stopping Thread
      13:04:32 : ** Thread Has STOPPED!
      13:04:32 : Done!


      On Oct 2, 4:40 pm, Todd Whiteman <to...@activest ate.comwrote:
      Steve wrote:
      >
      A better approach for this is to use a Python Event or Condition object:http://docs.python.org/library/threading.html#id5
      >
      Example code:
      >
      import threading
      my_stop_event = threading.Event ()
      >
             # Sleep Loop :
             #for current_loop in range(0, self.time_slice ) :
             #  time.sleep(self .sleep_time / self.time_slice )
      >
             event.wait(self .sleep_time)
             if not self.running:    # check the flag
               break                 # break out of the sleep loop
      >
      # From another thread, you can notify the above sleeping thread using:
      my_stop_event.s et()
      >
      Cheers,
      Todd

      Comment

      Working...