1

I want to create a thread class in python3. I want to control an infinite loop in one of the class function. I want to start or stop this loop in my main function outside the class. suppose this code:

import threading
from time import sleep
class my_thread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(my_thread, self).__init__()
        self._stop_event = threading.Event()

    def stop(self):
        print("stopping the thread")
        self._stop_event.set()

    def stopped(self):
        return(self._stop_event.is_set())

    def run(self):
        print("running the thread")
        print("start function startt()")
        self._stop_event.clear()
        self.startt()

    def startt(self):
        print("it is going to wait forever")
        while not self.stopped():
            #wait forever, this part is going to run again and again
            pass
        print("This line never executes")


if __name__+'__main__':
    thr=my_thread()
    thr.start()
    sleep(5)
    print("stopping the thread")
    thr.stop()
    # I cant start the thread and relative while loop again
    #thr.start()   
    print("Exiting the whole program")

But the problem is I can't start the thread twice, so what I want is to have two function for start and stop my while loop. I dont need to stop the thread but I need to control it. It means I want to call stop() and startt() functions for many times whenever needed in my main routine. Thanks

Masoud Rahimi
  • 5,785
  • 15
  • 39
  • 67
  • 1
    You can use a `Queue` to pass a command to a thread. - https://stackoverflow.com/questions/25904537/how-do-i-send-data-to-a-running-python-thread – Dror Av. Aug 10 '17 at 09:35
  • @droravr thanks for the tip but I'm thinking to use of event because it is simpler, how to use `Queue` for controlling a loop inside the thread? – Masoud Rahimi Aug 10 '17 at 09:40

1 Answers1

1

first, use Queue in my_thread class for manage task( method ) that complete or called by your thread

you can use LIFO Queue , Prioritry Queue ,FIFO Queue detail

second, add a class-method so you can add new method or task into the queue

add below code into your code :

from queue import Queue
# or
# from multiprocessing import Queue
class my_thread(threading.Thread):
    queue = Queue()

    @classmethod
    def add_task(cls,callable_task):
        cls.queue.put(callable_task)

    def startt(self):
        print("it is going to wait forever")
        while not self.stopped():
            #wait forever, this part is going to run again and again
            if not  self.queue.empty():
                  _m = self.queue.get()
                 # do what ever you want to do with _m

        print("This line never executes")

for stop thread

 Class my_thread(Threading.Thread)
     stop_event = threading.Event()

     @classmethod
     def stop_thread(cls)
         cls.stop_event.set()

     def startt(self):
         print("it is going to wait forever")
         cls = self.__class__
         while not cls.stop_event.is_set():
             #wait forever, this part is going to run again and again
             if not  self.queue.empty():
                 _m = self.queue.get()
                 # do what ever you want to do with _m

         print("This line never executes")

Now call for stop therad

  my_thread.stop_thread()

Exapmle

import threading
import time
class my_thread(threading.Thread):
    stop_event = threading.Event()

    @classmethod
    def stop_thread(cls):
        cls.stop_event.set()

    def run(self):
        print("running the thread")
        print("start function startt()")
        self.__class__.stop_event.clear()
        self.startt()

    def startt(self):
        print("it is going to wait forever")
        cls = self.__class__
        print cls.stop_event.is_set()
        while not cls.stop_event.is_set():
            pass

        print("This line never executes")

a = my_thread()
a.start()
time.sleep(0.5)
my_thread.stop_thread()
print "\n\n\n"
b = my_thread()
b.start()
time.sleep(0.5)
my_thread.stop_thread()
Kallz
  • 3,244
  • 1
  • 20
  • 38
  • Thanks for the answer. I tried your code but how can I start and stop the loop outside the class (in my main) and what is `_m`? – Masoud Rahimi Aug 10 '17 at 10:16
  • @MasoudR. I update my answer please check and add above code into your code and _m is object that add into queue – Kallz Aug 10 '17 at 10:29
  • I used both codes, but I get the same result as mine, in my example the stop method works fine but I can't start it again, if I call `startt()` function after calling `stop()` It stuck on the loop and can't call `stop()` function again. – Masoud Rahimi Aug 10 '17 at 10:40
  • I can't use it because `startt(`) function never ends, it has an infinite loop inside or maybe I'm using it in a wrong way. Can you please edit my code and put all codes to gather? – Masoud Rahimi Aug 10 '17 at 10:50
  • 1
    @MasoudR. you have to add time delay in the start and stop of thread and run above example with time delay and without time delay and check your printed output – Kallz Aug 10 '17 at 11:05
  • Thanks finally it solved my problem, actually I needed to declare the object of my thread if I want to start it again. I used your method with mine and both codes work now. But what is the point of `Queue` in my problem? – Masoud Rahimi Aug 10 '17 at 11:17