从目标函数内部停止线程?

时间:2016-09-02 17:47:18

标签: python multithreading

有没有办法可以在几秒钟后停止线程(内部)

t1 = Thread(target=call_script1, args=())
t2 = Thread(target=call_script2, args=())
t3 = Thread(target=call_script3, args=())

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

主程序等待直到线程返回。我想知道是否有办法 - 当我产生一个线程时 - 比如t2,它的目标是一个函数 - call_script2。让我们说功能需要5秒才能完全运行。我想知道我是否可以在3秒后回复帖子。

3秒后线程返回的能力应该在call_script2函数内。我相信在主线程中使用stop_event.wait(3)不起作用。

call_script2函数看起来像这样。

def InterfaceThread2():
    a = 1;
    d = 2
    i = 1
    while i ==1:
        #ser = serial.Serial(3, 115200)
        if ser.isOpen():
            ser.write('\x5A\x03\x02\x00\x02\x07')

            a = ser.read(7) #### THIS COMMAND WAITS UNTIL IT RECEIVES DATA FROM MCU
            ## This usually happens in 100ms in theory. If it is taking like more than 100ms -for safety say I will wait for three seconds and if it did not respond back
            ## I want to stop the thread and popup an error message.

        # Tell the GUI about the Information
        wx.CallAfter(pub.sendMessage, "APP_EVENT2", arg1 = a, arg2 = d)
        print "hello"

        time.sleep(1)
        i = i+1

2 个答案:

答案 0 :(得分:1)

我认为您可以使用timeout构造函数中提供的serial.Serial()参数来获取所需的行为。此外,您需要使用Serial保护与threading.Lock()实例的互动,以便您的线程在读取/写入数据时不会互相踩踏:

ser = serial.Serial(..., timeout=3, ...)
lock = Threading.Lock()

def call_script1():
    a = 1
    d = 2
    i = 1
    while i == 1:  # Lock is acquired here
        with lock:
            if ser.isOpen():
                ser.write('\x5A\x03\x02\x00\x02\x07')
                a = ser.read(7)
                if len(a) != 7:
                    # We didn't get all the bytes we wanted, a timeout
                    # must have occurred.
                    print("Only read {} bytes!".format(len(a)))
                    # Maybe exit or throw an exception?

        # Lock is released here.
        # Tell the GUI about the Information
        wx.CallAfter(pub.sendMessage, "APP_EVENT2", arg1 = a, arg2 = d)
        print "hello"

        time.sleep(1)
        i = i+1

def call_script2():
    while i == 1:
        with lock:
            if ser.isOpen():
                # Do whatever

def call_script3():
    while i == 1:
        with lock:
            if ser.isOpen():
                # Do whatever

t1 = Thread(target=call_script1, args=())
t2 = Thread(target=call_script2, args=())
t3 = Thread(target=call_script3, args=())

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

答案 1 :(得分:0)

Thread.join方法有一个可选的timeout参数。

# block until thread ``t`` completes, or just wait 3 seconds
t.join(3)

如果你希望目标函数处理这个超时逻辑,我建议写一个包装器来产生一个新线程,进行调用,然后以3秒超时加入。

from threading import Thread
import time

def counter(limit):
    for i in range(limit):
        print(i)
        time.sleep(0.1)

timeout = 3
def wrapper(*args, **kwargs):
    t = Thread(target=counter, args=args, kwargs=kwargs)
    t.daemon = True
    t.start()
    t.join(timeout)

t = Thread(target=wrapper, args=(100,))
t.start()
t.join()

请注意,在主进程终止之前,这实际上并不会杀死子线程。杀死一个线程而不知道它在里面做什么可能会造成各种各样的混乱。

如果您可以更改原始功能的代码,您可以让他们定期轮询以检查是否有人希望他们死亡。

编辑:看起来我有点误解了这个问题。更多的是关于如何使用PySerial在3个工作者之间共享1个开放Serial对象,并且从串行端口读取超时。