Tkinter hangs on rapidly repeated Dialog
<h3>The Problem</h3>

<p>When I repeatedly open a Dialog by holding down the Return key, the program
eventually hangs with the dialog open. Nothing is clickable, and no keyboard
shortcuts work. If I unfocus the window by clicking away, then click back to
it, the hang is gone.</p>

<p>When I repeatedly open a CustomDialog by holding down Shift-Return, the program doesn't hang.</p>

<h3>Questions</h3>

<ul>
<li>Why does the <code>Dialog</code> class sometimes make the program hang when rapidly and repeatedly opened?</li>
<li>Why does the <code>CustomDialog</code> class, which inherits from <code>Dialog</code> and only overwrites one line, not suffer from this problem?</li>
</ul>

<h3>Observations</h3>

<ul>
<li>The hang doesn't occur consistently. It happens more reliably when
I simultaneously run a cpu-intensive command, such as <code>cat /dev/urandom</code>.</li>
<li>Clicking the 'Open Dialog' button (instead of pressing Return) doesn't
seem to cause the program to hang. This might be because the mouse can't
click the button as quickly as the bound Return key can call
<code>MainWindow.open_dialog()</code>.</li>
</ul>

<h3>Example Code</h3>

<p>The code below creates a Tk window with two buttons:</p>

<ul>
<li>'Open Dialog' opens an instance of <code>tkinter.simpledialog.Dialog</code>.</li>
<li>'Open Custom Dialog' opens an instance of <code>CustomDialog</code>, which inherits
from <code>tkinter.simpledialog.Dialog</code>, but comments out a single line <a href="https://hg.python.org/cpython/file/3.5/Lib/tkinter/simpledialog.py#l215" rel="nofollow noreferrer">(line 215)</a>
of the <code>ok()</code> method.</li>
<li>The Return key is bound to the 'Open Dialog' button.</li>
<li>Shift+Return is bound to the 'Open Custom Dialog' button.</li>
<li>Setup:

<ul>
<li>Run the code below with Python 3.5.2.</li>
<li>Hold down the Return key.</li>
</ul></li>
</ul>

<h3>hangingdialog.py</h3>

<pre><code>import tkinter
from tkinter import ttk
from tkinter.simpledialog import Dialog


class MainWindow:

    def __init__(self):
        self.root = tkinter.Tk()

        self.btn_dialog = ttk.Button(
            self.root,
            text="Open Dialog",
            command=self.open_dialog,
        )

        self.btn_custom_dialog = ttk.Button(
            self.root,
            text="Open Custom Dialog",
            command=self.open_custom_dialog,
        )

        self.btn_dialog.pack()
        self.btn_custom_dialog.pack()

        self.root.bind('&lt;Return&gt;', self.open_dialog)
        self.root.bind('&lt;Shift-Return&gt;', self.open_custom_dialog)

        self.root.mainloop()

    def open_dialog(self, event=None):
        u = Dialog(self.root, 'Dialog')
        print('Dialog Opened.')

    def open_custom_dialog(self, event=None):
        u = CustomDialog(self.root, 'Custom Dialog')
        print('Custom Dialog Opened.')


class CustomDialog(Dialog):
    """This class is identical to is identical to
    tkinter.simpledialog.Dialog, but with
    'self.withdraw()' commented out in the self.ok()
    method.
    """

    def __init__(self, parent, title=None):
        tkinter.simpledialog.Dialog.__init__(self, parent, title)

    def ok(self, event=None):
        """This method is identical to
        tkinter.simpledialog.Dialog.ok(),
        but with 'self.withdraw()' commented out.
        """
        if not self.validate():
            self.initial_focus.focus_set() # put focus back
            return

        # Using self.withdraw() here causes the
        # ui to freeze until the window loses and regains
        # focus.
        #self.withdraw()
        self.update_idletasks()

        try:
            self.apply()
        finally:
            self.cancel()


if __name__ == '__main__':
    MainWindow()
</code></pre>