简体   繁体   English

为什么这个 asyncio 调用暂停执行?

[英]Why does this asyncio call pause execution?

Here is my code:这是我的代码:

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));

I have tried everything and it still seems that execution pauses after asyncio.run(runTaskWrapped(options));我已经尝试了一切,但似乎在asyncio.run(runTaskWrapped(options));之后执行暂停

Any idea why this may be?知道为什么会这样吗?

EDIT: I tried threading.Thread, and although it didn't pause execution, pysimplegui (imported as sg) didnt do anything and no window showed up for it like it does when called synchronously.编辑:我尝试了threading.Thread,虽然它没有暂停执行,但pysimplegui(导入为sg)没有做任何事情,也没有像同步调用时那样出现window。

I tried trio too, but trio paused execution.我也尝试了三重奏,但三重奏暂停了执行。 trio.run(runTaskWrapped, options);

When you call asyncio.run(some_function()), your program will not go to the next line until some_function() returns.当您调用 asyncio.run(some_function()) 时,您的程序不会 go 到下一行,直到 some_function() 返回。 In your case, runTaskWrapped doesn't return until you execute one of its "break" statements.在您的情况下, runTaskWrapped 在您执行其“中断”语句之一之前不会返回。

We deal with this sort of thing all the time.我们一直在处理这类事情。 If you call any function f(), your program won't continue until f() returns.如果您调用任何 function f(),您的程序将不会继续,直到 f() 返回。 That's a familiar concept.这是一个熟悉的概念。

What's different about asyncio is that it creates a loop of its own, called the event loop, and launches some_function() from inside that loop. asyncio 的不同之处在于它创建了一个自己的循环,称为事件循环,并从该循环内启动 some_function()。 That allows you to start other tasks from within some_function(), and those other tasks get a chance to execute when some_function() encounters an "await" statement.这允许您从 some_function() 中启动其他任务,并且当 some_function() 遇到“await”语句时,这些其他任务有机会执行。 That's a powerful concept if that's what you need.如果这是您需要的,那将是一个强大的概念。 But it's only useful if you have two or more tasks that need to wait on external resources, like a network or a serial communications link, and one of the tasks can proceed while the other is waiting.但只有当您有两个或多个任务需要等待外部资源(例如网络或串行通信链路)并且其中一个任务可以在另一个任务等待时继续进行时,它才有用。

Your function runTaskWrapped does not contain any "await" statements.您的 function runTaskWrapped 不包含任何“等待”语句。 So asyncio creates an event loop, hands control to runTaskWrapped.所以 asyncio 创建了一个事件循环,将控制权交给 runTaskWrapped。 That's a blind alley.那是一条死胡同。 It is more-or-less an infinite loop and doesn't "await" anything.它或多或少是一个无限循环,并且不会“等待”任何东西。 Therefore there is no way out of runTaskWrapped, and your program is effectively dead at that point.因此,runTaskWrapped 没有出路,此时您的程序实际上已经死了。

In order to make use of asyncio you must structure your program to have more than one task containing "await"s.为了使用 asyncio,您必须将您的程序构造为具有多个包含“await”的任务。

You are writing a GUI program, which typically means that it already has an event loop of its own.您正在编写一个 GUI 程序,这通常意味着它已经拥有自己的事件循环。 In some cases it is possible to run the GUI's event loop and the asyncio event loop together, but unless you have a specific need to do this it doesn't gain you anything.在某些情况下,可以同时运行 GUI 的事件循环和 asyncio 事件循环,但除非您有特殊需要这样做,否则它不会为您带来任何好处。

You are also trying to use asyncio with multiple threads, and although this is possible it needs to be done quite carefully.您还尝试将 asyncio 与多个线程一起使用,尽管这是可能的,但需要非常小心地完成。 You can start other threads just as in any other Python program, but the presence of those other threads doesn't change what happens in your main thread.您可以像在任何其他 Python 程序中一样启动其他线程,但是这些其他线程的存在不会改变您的主线程中发生的事情。 You must specifically write code to synchronize events between threads.您必须专门编写代码来同步线程之间的事件。

No matter what you do in those other threads, asyncio.run(some_function()) will not return until its argument is finished.无论您在其他线程中做什么, asyncio.run(some_function()) 在其参数完成之前都不会返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM