为什么这个 asyncio 调用暂停执行?
Why does this asyncio call pause execution?
这是我的代码:
async def runTaskWrapped(options):
layoutz = [[sg.Text("Running...", key="runstatus")]];
windowz = sg.Window("New Task", layoutz);
x = threading.Thread(target=runTask, args=(options,));
x.start();
startTime = time.time();
while True:
eventz, valuesz = windowz.read(timeout=100)
if eventz == sg.WIN_CLOSED:
if x.is_alive():
continue
break
if x.is_alive() == False:
x.join()
windowz.FindElement('runstatus').Update(value='Done! Check the new log.txt for more info.');
break;
else:
windowz.FindElement('runstatus').Update(value='Running... (' + str(math.floor(time.time()-startTime)) + ')')
asyncio.run(runTaskWrapped(options));
我已经尝试了所有方法,但在 asyncio.run(runTaskWrapped(options));
之后执行似乎仍然暂停
知道为什么会这样吗?
编辑:
我尝试了 threading.Thread,虽然它没有暂停执行,但 pysimplegui(导入为 sg)没有做任何事情,也没有 window 像同步调用时那样出现。
我也试过trio,但是trio暂停了执行。
trio.run(runTaskWrapped, options);
当您调用 asyncio.run(some_function()) 时,您的程序将不会转到下一行,直到 some_function() returns。在您的情况下,运行TaskWrapped 不会 return 直到您执行其“中断”语句之一。
我们经常处理这种事情。如果你调用任何函数 f(),你的程序将不会继续,直到 f() returns。这是一个熟悉的概念。
asyncio 的不同之处在于它创建了自己的循环,称为事件循环,并从该循环内部启动 some_function()。这允许您从 some_function() 中启动其他任务,并且当 some_function() 遇到“await”语句时,这些其他任务有机会执行。如果这是您所需要的,那将是一个强大的概念。但它只有在您有两个或多个任务需要等待外部资源(如网络或串行通信)时才有用link,并且其中一个任务可以在另一个任务等待时继续进行。
您的函数 运行TaskWrapped 不包含任何“await”语句。因此 asyncio 创建了一个事件循环,将控制权交给 运行TaskWrapped。那是一条死胡同。它或多或少是一个无限循环,不会“等待”任何东西。因此,没有办法摆脱 运行TaskWrapped,此时您的程序实际上已经死了。
为了使用 asyncio,您必须构建您的程序,使其具有多个包含“await”的任务。
您正在编写一个 GUI 程序,这通常意味着它已经有自己的事件循环。在某些情况下,可以 运行 GUI 的事件循环和 asyncio 事件循环一起进行,但除非您有特殊需要这样做,否则它不会给您带来任何好处。
您还尝试将 asyncio 与多线程一起使用,尽管这是可能的,但需要非常小心地完成。您可以像在任何其他 Python 程序中一样启动其他线程,但这些其他线程的存在不会改变主线程中发生的事情。您必须专门编写代码来同步线程之间的事件。
无论您在其他线程中做什么,asyncio.run(some_function()) 都不会 return 直到其参数完成。
这是我的代码:
async def runTaskWrapped(options):
layoutz = [[sg.Text("Running...", key="runstatus")]];
windowz = sg.Window("New Task", layoutz);
x = threading.Thread(target=runTask, args=(options,));
x.start();
startTime = time.time();
while True:
eventz, valuesz = windowz.read(timeout=100)
if eventz == sg.WIN_CLOSED:
if x.is_alive():
continue
break
if x.is_alive() == False:
x.join()
windowz.FindElement('runstatus').Update(value='Done! Check the new log.txt for more info.');
break;
else:
windowz.FindElement('runstatus').Update(value='Running... (' + str(math.floor(time.time()-startTime)) + ')')
asyncio.run(runTaskWrapped(options));
我已经尝试了所有方法,但在 asyncio.run(runTaskWrapped(options));
知道为什么会这样吗?
编辑: 我尝试了 threading.Thread,虽然它没有暂停执行,但 pysimplegui(导入为 sg)没有做任何事情,也没有 window 像同步调用时那样出现。
我也试过trio,但是trio暂停了执行。
trio.run(runTaskWrapped, options);
当您调用 asyncio.run(some_function()) 时,您的程序将不会转到下一行,直到 some_function() returns。在您的情况下,运行TaskWrapped 不会 return 直到您执行其“中断”语句之一。
我们经常处理这种事情。如果你调用任何函数 f(),你的程序将不会继续,直到 f() returns。这是一个熟悉的概念。
asyncio 的不同之处在于它创建了自己的循环,称为事件循环,并从该循环内部启动 some_function()。这允许您从 some_function() 中启动其他任务,并且当 some_function() 遇到“await”语句时,这些其他任务有机会执行。如果这是您所需要的,那将是一个强大的概念。但它只有在您有两个或多个任务需要等待外部资源(如网络或串行通信)时才有用link,并且其中一个任务可以在另一个任务等待时继续进行。
您的函数 运行TaskWrapped 不包含任何“await”语句。因此 asyncio 创建了一个事件循环,将控制权交给 运行TaskWrapped。那是一条死胡同。它或多或少是一个无限循环,不会“等待”任何东西。因此,没有办法摆脱 运行TaskWrapped,此时您的程序实际上已经死了。
为了使用 asyncio,您必须构建您的程序,使其具有多个包含“await”的任务。
您正在编写一个 GUI 程序,这通常意味着它已经有自己的事件循环。在某些情况下,可以 运行 GUI 的事件循环和 asyncio 事件循环一起进行,但除非您有特殊需要这样做,否则它不会给您带来任何好处。
您还尝试将 asyncio 与多线程一起使用,尽管这是可能的,但需要非常小心地完成。您可以像在任何其他 Python 程序中一样启动其他线程,但这些其他线程的存在不会改变主线程中发生的事情。您必须专门编写代码来同步线程之间的事件。
无论您在其他线程中做什么,asyncio.run(some_function()) 都不会 return 直到其参数完成。