尽快停止一个线程,而不必在每行代码前加上 "if not running: break"?

问题描述 投票:0回答:1

上下文。我已经看过了 有什么方法可以杀死一个Thread? 以及它的答案,但在这里,我专注于一个可能的解决方案,用一个函数(在一个包装器内?running 临行 线程目标函数的代码行。而且我已经阅读了 Python,停止一个线程 但这并不能解决问题,因为标志检查的 "颗粒度 "是每次只检查一次 while 循环,而我希望它在每一行代码中都有。


下面的代码(为这个问题简化)。

import threading, time

def character_loop():
    while running:
        print('character moving left')
        time.sleep(1)
        print('character moving middle')
        time.sleep(1)
        print('character moving right')
        time.sleep(1)

running = True
threading.Thread(target=character_loop).start()
time.sleep(4.5)
running = False     # how to stop *any* movement here?
time.sleep(10)

它实际上是在做 两种 充分 环路左中右左中右而我希望在4.5秒后停止任何动作。

如何拥有 left/mid/right/left/<stop here!> 而不是?

换句话说,如何能够尽快停止一个线程?(可能是在线程中运行的每一行代码之后) target 函数)

这样就可以了。

def character_loop():
    while running:
        print('character moving left')
        if not running: 
            break
        time.sleep(1)
        if not running: 
            break
        print('character moving middle')
        if not running: 
            break
        time.sleep(1)
        if not running: 
            break
        print('character moving right')
        if not running: 
            break
        time.sleep(1)

但必须加上

if not running: 
    break

在主循环中的每行代码之后,都会有一个 "主循环",这真的很烦人。

我相信有一个通用的线程调度方案可以解决这个问题。如何尽快停止一个线程函数,最好是在每行代码之后,而不仅仅是在函数返回时才停止 while running:?


PS:在我的真实代码中,不仅仅是有了 print('character moving left') 但另一个函数,根据动作的不同,需要几毫秒到几秒才能完成。

python multithreading scheduler python-multithreading scheduling
1个回答
1
投票

从使用线程切换到支持立即取消任务的asyncio。然而这可能会被证明是困难的,这取决于代码的结构。你将需要在主线程中启动一个asyncio循环。目前,这是用 asyncio.run()main()但在你的实施中会有所不同。

import asyncio


async def runner():
    try:
        while True:
            print("left")
            await asyncio.sleep(1)
            print("mid")
            await asyncio.sleep(1)
            print("right")
            await asyncio.sleep(1)
    except asyncio.CancelledError:
        print("Task was canceled")


async def main():
    # In Python 3.7+
    task = asyncio.create_task(runner())
    # This works in all Python versions but is less readable
    # task = asyncio.ensure_future(runner())
    await asyncio.sleep(4.5)
    task.cancel()
    await asyncio.sleep(5)


if __name__ == "__main__":
    asyncio.run(main())
© www.soinside.com 2019 - 2024. All rights reserved.