如何构造代码以便能够启动可以相互杀死/替换的任务

时间:2016-01-07 16:50:48

标签: python python-multithreading

我有一个Python程序,它执行以下操作: 1)无休止地等待com端口一个命令字符 2)在字符接收时,启动一个新线程来执行特定的代码

如果收到新命令,我需要做的是: 1)杀死前一个帖子 2)推出一个新的

我在这里和那里读到这样做并不是正确的方法。 知道我需要在同一个过程中执行此操作的最佳方法是什么,所以我想我需要使用线程......

4 个答案:

答案 0 :(得分:1)

我建议你采用两种不同的方法:

  • 如果您的进程同时从一个函数内部调用,您可以在第一个函数上set a timeout
  • 如果您正在运行外部脚本,则可能需要kill the process

答案 1 :(得分:0)

可能希望在单独的线程中运行串行端口。当它接收到一个字节时将该字节放入队列中。让主程序循环并检查队列以决定如何处理它。从主程序中,您可以使用join来终止线程并启动一个新线程。您可能还想查看一个线程池,看看它是否是您想要的。

ser = serial.Serial("COM1", 9600)
que = queue.Queue()

def read_serial(com, q):
    val = com.read(1)
    q.put(val)

ser_th = threading.Thread(target=read_serial, args=(ser, que))
ser_th.start()

th = None
while True:
    if not que.empty():
        val = que.get()
        if val == b"e":
            break # quit
        elif val == b"a":
            if th is not None:
                th.join(0) # Kill the previous function
            th = threading.Thread(target=functionA)
            th.start()
        elif val == b"b":
            if th is not None:
                th.join(0) # Kill the previous function
            th = threading.Thread(target=functionB)
            th.start()
        elif val == b"c":
            if th is not None:
                th.join(0) # Kill the previous thread (functionA)
            th = threading.Thread(target=functionC)
            th.start()

try:
    ser.close()
    th.join(0)
except: 
    pass

如果您正在创建并加入大量线程,您可能希望只有一个函数来检查要运行的命令。

running = True
def run_options(option):
    if option == 0:
        print("Running Option 0")
    elif option == 1:
        print("Running Option 1")
    else:
        running = False

while running:
    if not que.empty():
        val = que.get()
        run_options(val)

答案 2 :(得分:0)

让我通过添加代码结构的示例来更加精确地解决我的问题。

假设同步functionA仍然在运行,因为在内部等待特定事件,如果收到命令“c”,我需要停止functionA并启动functionC。

 def functionA():
    ....
    ....
    call a synchronous serviceA that can take several seconds even more to execute
    ....
    ....


def functionB():
    ....
    ....
    call a synchronous serviceB that nearly returns immediately
    ....
    ....


def functionC():
    ....
    ....
    call a synchronous serviceC
    ....
    ....    


#-------------------

def launch_async_task(function):

    t = threading.Thread(target=function, name="async")
    t.setDaemon(True)
    t.start()


#------main----------

while True:
    try:
        car = COM_port.read(1)

        if      car == "a":
                    launch_async_task(functionA)

        elif    car == "b":
                    launch_async_task(functionB)

        elif    car == "c":
                    launch_async_task(functionC)

答案 3 :(得分:0)

好吧,我终于使用了一段使用ctypes lib的代码来提供某种杀戮线程功能。 我知道这不是一个干净的方法,但在我的情况下,线程没有共享资源,所以它不会产生任何影响......

如果可以提供帮助,可以在网上轻松找到这段代码:

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")