Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何构造代码,以便能够启动可以相互杀死/替换的任务_Python_Python Multithreading - Fatal编程技术网

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

Python 如何构造代码,以便能够启动可以相互杀死/替换的任务,python,python-multithreading,Python,Python Multithreading,我有一个Python程序,可以执行以下操作: 1) 在com端口上无休止地等待命令字符 2) 在接收字符时,启动一个新线程来执行一段特定的代码 如果收到新命令,我需要做的是: 1) 杀死上一个线程 2) 推出一个新的 我到处读到这样做不是正确的方式。 如果知道我需要在同一个过程中执行此操作,那么我想我需要使用线程…我建议您使用两种不同的方法: 如果您的进程都是从一个函数内部调用的,则可以在第一个函数上调用 如果正在运行外部脚本,则可能需要 可能需要在单独的线程中运行串行端口。当它收到一个字节时

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

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

我到处读到这样做不是正确的方式。
如果知道我需要在同一个过程中执行此操作,那么我想我需要使用线程…

我建议您使用两种不同的方法:

  • 如果您的进程都是从一个函数内部调用的,则可以在第一个函数上调用
  • 如果正在运行外部脚本,则可能需要

    • 可能需要在单独的线程中运行串行端口。当它收到一个字节时,将该字节放入队列中。让主程序循环并检查队列以决定如何处理它。在主程序中,您可以使用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)
      

      让我通过添加一个代码结构示例来更精确地回答我的问题

      假设同步Function由于在内部等待特定事件而仍在运行,如果收到命令“c”,我需要停止Function并启动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)
      

      好的,我最后使用了一段代码,它使用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")
      

      我不认为超时解决方案有什么意义,因为我不希望函数在一段时间后退出,但我希望它在调用另一个函数后退出。您是否尝试过多处理?否则,您可以调用第二个函数作为第一个函数中的最后一个语句。如果我不明白,你可以发布你的代码摘要吗?我只是在下面发布了一个例子。希望它现在更清楚。我觉得你的答案可以帮助我,但我不知道如何适应我的代码,我张贴后的具体情况。。。一个想法?你必须有一种方法杀死正在运行的函数,这样你才能结束线程。我改变了我发布的第一个选项,向你展示了它是如何工作的。我刚刚尝试了你的新建议,但我无法消除之前的线程。一旦收到新命令,它仍将继续运行。我不明白th.join(0)怎么会杀死任何函数……你必须想出一种杀死函数的方法。线程连接将在线程退出其运行方法(functo)时结束线程。有一些终止线程的方法,但不推荐使用。好的,这就是为什么联接(0)没有终止任何内容。我想做的是在收到命令后立即退出我的功能!我试图找到一种方法,在每个可终止函数中插入一些公共代码,比如在特定条件下可能退出的while循环。