Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dialogs (such as messagebox) block async mainloop #39

Open
insolor opened this issue Apr 27, 2023 · 5 comments
Open

Dialogs (such as messagebox) block async mainloop #39

insolor opened this issue Apr 27, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@insolor
Copy link
Owner

insolor commented Apr 27, 2023

In the following code (pure tkinter) counter continues to work while messagebox dialog is shown:

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()


def loop():
    counter.set(counter.get() + 1)
    root.after(1000, loop)


def show_message():
    messagebox.showinfo("Info", "Some info")


counter = tk.IntVar()
tk.Label(root, textvariable=counter).pack()

tk.Button(root, text="Start counter", command=loop).pack()
tk.Button(root, text="Show message", command=show_message).pack()

root.mainloop()

But with the corresponding code with async_tkinter_loop counter is paused when messagebox is shown:

import asyncio
import tkinter as tk
from tkinter import messagebox
from async_tkinter_loop import async_mainloop, async_handler

root = tk.Tk()


@async_handler
async def loop():
    while True:
        counter.set(counter.get() + 1)
        await asyncio.sleep(1.0)


def show_message():
    messagebox.showinfo("Info", "Some info")


counter = tk.IntVar()
tk.Label(root, textvariable=counter).pack()

tk.Button(root, text="Start counter", command=loop).pack()
tk.Button(root, text="Show message", command=show_message).pack()

async_mainloop(root)
@insolor insolor added the bug Something isn't working label Apr 27, 2023
@ra1u
Copy link

ra1u commented Feb 18, 2024

Thank you for this libraray:
I got same issue.

My solution was to turn things around.
Instead of running tkinter on top of async, it runs async loop inside tkinter.

We start tkinter and register callback 1ms later.
In callback from tkinter we do blocking call

  1. register async task 5ms later to stop async loop
  2. we run loop "forewer"
  3. when we unblock 5ms later, we register same tkinter callback 1ms later

Proof of concept:
https://gist.github.com/ra1u/8aa66c09e985dd2a9fe297bcd222ddf7

@insolor
Copy link
Owner Author

insolor commented Feb 27, 2024

@ra1u interesting, I'll take a look later

@ghmanoj
Copy link

ghmanoj commented Aug 23, 2024

@insolor Any updates on this?
Most probably the issue I am facing is also related to this.
When I let a long running async function start and then drag the tkinter window the async function pauses and continues again only after I leave the window from dragging.

@insolor
Copy link
Owner Author

insolor commented Aug 23, 2024

@ghmanoj this is probably a similar problem, but not the same one. In your case, if you need a non-stopping async function try to run the function in a separate thread, it should help (it won't help with dialogs though).

@ra1u
Copy link

ra1u commented Aug 23, 2024

If i recall correctly there is "bug" in MS Windows tkinter, that when you drag window around holding top menu bar, there is 100% cpu utilisation, because Windows is sending lot notifications on tkinter. Workaround is, that you replace default top bar, with tkinter widget including custom bar and custom X button on right.
I am not sure that what is presented in current issue will help with this 100% cpu issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants