About asyncio loop handling in BlenderCloud addon #49275
Labels
No Label
Interest
Animation & Rigging
Interest
Blender Cloud
Interest
Collada
Interest
Core
Interest
Documentation
Interest
Eevee & Viewport
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
Import and Export
Interest
Modeling
Interest
Modifiers
Interest
Nodes & Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds, Tests & Devices
Interest
Python API
Interest
Rendering & Cycles
Interest
Sculpt, Paint & Texture
Interest
Translations
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Meta
Good First Issue
Meta
Papercut
Module
Add-ons (BF-Blender)
Module
Add-ons (Community)
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender-addons#49275
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
So, have been banging my head against the issue of running asyncio's loop as a sub-loop of Blender one, trying to understand how the
kick_async_loop()
can actually work - and failing so far.As far as I understand, asyncio loop is run by the addon that way:
kick_async_loop()
) to “make advance” the asyncio loop.My problem is with that loop kicker: outside of some 'break' checks, it basically calls
loop.stop()
, and immediately afterloop.run_forever()
. Butloop.run_forever()
is blocking, right? It will only return onceloop.stop()
has been called. In other words, we are blocking the main thread (i.e. the whole Blender itself!) waiting for asyncio loop to suspend itself.Which leads me to think that this cannot (should not!) actually work, unless maybe it does currently because you limit number of simultaneous pillar connections to 3?
Anyway, @dr.sybren, can you confirm that, or explain me how you stop the loop once launched? ;) get back to the
For own work (asset engines in asset-engine branch), after a lot of hours banging my head against the issue, I think I found the (correct?) solution: you have to schedule the call to
loop.stop()
before callingloop.run_forever()
(with eithercall_soon()
or, if you want to leave some more processing time to your loop,call_later()
with reasonably small delay (below 1ms for sure)). That way, you can safely run a step or a small bit of the loop, and quickly get back the hand over main thread. ;)Changed status to: 'Open'
Added subscribers: @dr.sybren, @mont29
The
select()
calls in asyncio are pretty smart, so it doesn't wait around for data to appear. This is why it can very quickly relinquish execution to Blender.The call to
loop.stop()
is there because asyncio doesn't have aloop.run_one_iteration()
method. However, from what I've seen, this simulates it quite well. Theloop.stop()
call sets a flag that's checked at the end of a loop iteration. Effectively it makes asyncio do whatever can be done now, then stops it again.We could run the asyncio loop in a separate thread, or even using a
ThreadPoolExecutor
in multiple parallel threads. That would have the advantage that it can keep running, and doesn't need any "kicking". However, it also introduces all the difficulty associated with multithreaded code. As a result, it prevents any async code from calling Blender functions or modifying Blender state, which is IMO a very big downside. With the code in the current state, there is little difference between what you can do in an async function and a regular one. Async-running operators can simply useself.report()
to notify the user of events. If this ability disappears, we should have a well thought-out way to communicate with the user that's thread-safe.Ah OK, I see know… so basically, calling (assuming loop is currently stopped of course):
is essentially the same thing as
…right? So now things make sense, thanks! :)
I still remain unconvinced about the non-threadibility of the thing though, imho it would allow much more flexibility, and enforce more sane code by precisely preventing ability to call Blender stuff from everywhere. ;) But I do see how it can make things more easy on the other hand, so… can live with it!
Be sure to check whether
loop.call_soon(loop.stop)
doesn't starve otherloop.call_soon(...)
calls. Those are the tricky undocumented behaviours we might want to check in a unit test or something.Changed status from 'Open' to: 'Archived'
Eeeh, think we can close that one for now :)