用函数控制python线程

时间:2014-12-02 16:55:42

标签: python multithreading

感谢那些帮助我弄清楚我需要使用线程在我运行的控制脚本中运行循环的人,我现在有一个问题是尝试控制线程 - 通过基于函数启动或停止它: 我想开始一个过程让电机在一个基于“开始”的运动中循环。参数发送到控制功能,我也想发送一个'停止'停止线程的参数 - 这是我到达的地方:

def looper():
     while True:
            print 'forward loop'
            bck.ChangeDutyCycle(10)
            fwd.ChangeDutyCycle(0)
            time.sleep(5)
            print 'backwards loop'
            bck.ChangeDutyCycle(0)
            fwd.ChangeDutyCycle(20)
            time.sleep(5)


def looper_control(state):
    t = threading.Thread(target=looper)
    if state == 'start':
       t.start()
    elif state == 'stop':
       t.join()
       print 'looper stopped!!'

当我调用looper_control('start')时,这会启动线程,但在looper_control('stop')时抛出错误:

  File "/usr/lib/python2.7/threading.py", line 657, in join
    raise RuntimeError("cannot join thread before it is started")
RuntimeError: cannot join thread before it is started

编辑:从这里调用looper_control

  if "motor" in tmp:
       if tmp[-1:] == '0':
          #stop both pin
          MotorControl('fwd',0,0)
          print 'stop motors'
          looper_control('stop')
       elif tmp[-1:] == '2':
          #loop the motor
          print 'loop motors'
          looper_control('start')

更新:我无法使用建议的方法停止线程 - 我以为我拥有它!

我在哪里:

class sliderControl(threading.Thread):
    def __init__(self,stop_event):
            super(sliderControl,self).__init__()
            self.stop_event = stop_event

    def run(self):
            while   self.stop_event:
                    print 'forward loop'
                    bck.ChangeDutyCycle(10)
                    fwd.ChangeDutyCycle(0)
                    time.sleep(5)
                    print 'backwards loop'
                    bck.ChangeDutyCycle(0)
                    fwd.ChangeDutyCycle(20)
                    time.sleep(5)


def looper_control(state,stop_event):
   if state == 'start':
       t = sliderControl(stop_event=stop_event)
       t.start()
   elif state == 'stop':
       #time.sleep(3)
       stop_event.set()
       #t.join()          
       print 'looper stopped!!'

来自:

   if tmp[-1:] == '0':
          #stop both pin
          MotorControl('fwd',0,0)
          print 'stop motors'
          #stop_thread_event = threading.Event()
          print 'stopping thread'
          print  stop_thread_event
          looper_control('stop',stop_thread_event)
       elif tmp[-1:] == '2':
          #loop the motor
          print 'loop motors'
          global stop_thread_event
          stop_thread_event = threading.Event()
          print stop_thread_event
          looper_control('start', stop_thread_event)

看起来像一个单独的线程事件被循环和停止调用,所以我认为全局会将其排除,但它只是不打球。当我开始循环 - 它运行,但当我试图阻止它,我得到looper停止! ,但这个过程一直在运行

3 个答案:

答案 0 :(得分:1)

您的顶级线程例程需要成为一个事件处理程序,用于侦听消息中的Queue对象(如from Queue import Queue),然后根据状态处理它们。其中一条消息可以是一个shutdown命令,在这种情况下主线程函数只是退出,允许主线程join

而不是time.sleep,使用threading.Timer与定时器的主体向您的事件队列发送消息。

这是一次重大的重构。但特别是如果您计划添加更多条件,您将需要它。另一种方法是使用一个处理此类事情的包,可能是pykka

答案 1 :(得分:1)

要停止python线程,可以使用threading.Event()

试试这个:

class YourClass(threading.Thread):
    def __init__(self, stop_event):
        super(YourClass, self).__init__()
        self.stop_event = stop_event

    def run(self):
        while not self.stop_event.is_set():
            # do what you need here (what you had in looper)

def looper_control(state, stop_event):
    if state == 'start':
        t = YourClass(stop_event=stop_event)
        t.start()
    elif state == 'stop':
        stop_event.set()

并调用looper_control:

stop_thread_event = threading.Event()
looper_control(state, stop_thread_event)

答案 2 :(得分:0)

你只能在线程“开始” 但你可以锁定和解锁线程。 停止和启动线程的最佳方法是使用互斥锁,例如:

#!/usr/bin/python

import threading
from time import sleep
mutex2 = threading.Lock()

#This thread add values to d[]
class Hilo(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while True:
            mutex2.acquire()
            #Add values to d[]
            d.append("hi from Peru")
            mutex2.release()
            sleep(1)

d=[];
hilos = [Hilo()]

#Stop Thread
#If you have more threads you need make a mutex for every thread
mutex2.acquire()

#Start treades, but the thread is lock
for h in hilos:
    h.start()
#so you need do
#unlock THREAD<
mutex2.release()
#>START THREAD

#Sleep for 4 seconds
sleep(4)
#And print d[]
print d
print "------------------------------------------"
#WAIT 5 SECONDS AND STOP THE THREAD
sleep(5)
try:
    mutex2.acquire()
except Exception, e:
    mutex2.release()
    mutex2.acquire()
#AND PRINT d[]
print d
#AND NOW YOUR TRHEAD IS STOP#

#When the thread is lock(stop), you only need call: mutex2.release()  for unlock(start)
#When your thread is unlock(start) and you want lock(stop):
#try:
#    mutex2.acquire()
#except Exception, e:
#    mutex2.release()
#    mutex2.acquire()