RuntimeError when showing dialog from async handler in Cocoa
See original GitHub issueDescribe the bug
A runtime error “Cannot enter into task while another task is being executed” is raised when showing a dialog from an async callback. This only occurs when there is already a “background task” running, either scheduled manually with asyncio.create_task
or through toga with toga.App.add_background_task
. The background task then crashes.
To Reproduce
Example code to reproduce, adapted from the handlers example:
Example
import asyncio
import toga
from toga.constants import COLUMN
from toga.style import Pack
class HandlerApp(toga.App):
async def do_async(self, widget, **kwargs):
widget.enabled = False
for i in range(1, 10):
self.async_label.text = "Iteration {}".format(i)
if not self.ask_to_continue():
break
self.async_label.text = "Ready."
widget.enabled = True
def ask_to_continue(self):
return self.main_window.confirm_dialog('Continue?', 'Press OK to continue.')
async def do_background_task(self, widget, **kwargs):
while True:
self.counter += 1
self.label.text = "Background: Iteration {}".format(self.counter)
await asyncio.sleep(1)
def startup(self):
self.main_window = toga.MainWindow(title=self.name)
self.label = toga.Label('Ready.', style=Pack(padding=10))
self.async_label = toga.Label('Ready.', style=Pack(padding=10))
self.counter = 0
self.add_background_task(self.do_background_task)
btn_style = Pack(flex=1)
btn_async = toga.Button('Async callback', on_press=self.do_async, style=btn_style)
box = toga.Box(
children=[
self.label,
btn_async,
self.async_label,
],
style=Pack(
flex=1,
direction=COLUMN,
padding=10
)
)
self.main_window.content = box
self.main_window.show()
def main():
return HandlerApp('Handlers', 'org.beeware.handlers')
if __name__ == '__main__':
app = main()
app.main_loop()
This raises the exception:
Exception ignored on calling ctypes callback function: <function CFTimerHandle._cf_timer_callback.<locals>.cf_timer_callback at 0x114c4e670>
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/rubicon/objc/eventloop.py", line 155, in cf_timer_callback
callback(*args)
File "/usr/local/lib/python3.8/site-packages/rubicon/objc/eventloop.py", line 304, in _callback
context.run(callback, *args)
RuntimeError: Cannot enter into task <Task pending name='Task-1' coro=<handler_with_cleanup() running at /usr/local/lib/python3.8/site-packages/toga/handlers.py:25> wait_for=<Future finished result=None>> while another task <Task pending name='Task-2' coro=<handler_with_cleanup() running at /usr/local/lib/python3.8/site-packages/toga/handlers.py:25>> is being executed.
Expected behavior The background task should pause while the dialog is blocking the event loop and resume afterwards.
Environment:
- Operating System: macOS Catalina, macOS Big Sur
- Python version: 3.8.5
- Software versions:
- Toga: 0.3.0.dev23
Additional context This may be an issue with the Cocoa event loop integration in rubicon.objc.
Issue Analytics
- State:
- Created 3 years ago
- Comments:11 (9 by maintainers)
Top Results From Across the Web
Why does the async/await code to show my ContentDialog ...
So I changed the code to this, adding "async" to the method/event handler and "await" to the call to show the content dialog:...
Read more >Xcode 14 Release Notes | Apple Developer Documentation
Fixed: Objective-C documentation for multi-language APIs show Swift symbol relationships instead of Objective-C relationships. (91627374).
Read more >Changelog — Python 3.11.1 documentation
gh-65802: Document handling of extensions in Save As dialogs. ... RuntimeError: Event loop is closed on interpreter exit after asynchronous socket activity.
Read more >Changes in Data Abstract for Cocoa
No changes for Data Abstract for Cocoa, in this release ... if schema fails to download in SQL Explorer; show error icon &...
Read more >更新日志 — Python 3.7.6 文档
Calling the previous signal handler in faulthandler signal handler uses more ... bpo-37929: IDLE Settings dialog now closes properly when there is no...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
“barely documented” seems even an exaggeration: the “reference” doc for
add_background_task(handler)
won’t even specify the signature ofhandler
, so much so that I have to reverse engineer it 😃(incidentally, AFAICT, it gets invoked with two “app variants”? my main class (a
toga.App
) and atoga_iOS.app.App
?)I would like to know how you did to call another screen, could you show the code?