EndModal from PyEvent fails to close dialog

Another day, another problem. I have a progress dialog that is shown during
a lengthy operation (copying several files) in a background thread. The
thread communicates with the dialog with custom PyEvents, with a source
taken from the wxPython demo.

Everything works but: If, from the event callback, I try to do
wxDialog.EndDialog() the dialog closes, but ShowModal() never returns -> the
process never ends.

Here is an example that exhibits this behaviour. First three events are
generated (changing the title of the box), then a close event is posted. The
dialog is closed, but ShowModal() never returns.

If you comment out the line "thread.start_new_thread", you can normally
close the dialog with the cancel button.

---------- SAMPLE CODE ----------

import wx, os, thread, time

def CopyFilesThread(target):
    for filename in range(3):
        evt = CopyFileEvent(str(filename))
        wx.PostEvent(target, evt)
        time.sleep(1)

    evt = CopyFileEvent(None)
    wx.PostEvent(target, evt)

wx.EVT_COPY_FILE = wx.NewEventType()

def EVT_COPY_FILE(win, func):
    win.Connect(-1, -1, wx.EVT_COPY_FILE, func)

class CopyFileEvent(wx.PyEvent):
    def __init__(self, args):
        wx.PyEvent.__init__(self)
        self.SetEventType(wx.EVT_COPY_FILE)
        self.args = args

class MyDialog(wx.Dialog):
    def __init__(self):
        wx.Dialog.__init__(self,None,1010,
            "Operation in progress",
            wx.DefaultPosition, wx.Size(393,168))
        self.m_btCancel = wx.Button(self,
            wx.ID_CANCEL,"Cancel",wx.Point(162,100),
            wx.Size(75,23),style=0)
        EVT_COPY_FILE(self, self.onCopyFileEvent)
        thread.start_new_thread(
            lambda: CopyFilesThread(self),())

    def onCopyFileEvent(self, evt):
        print "GOT EVENT %s" % str(evt.args)
        if evt.args is None:
            self.EndModal(wx.ID_CANCEL)
        else:
            self.SetTitle(evt.args)
        evt.Skip()

class MyApp(wx.App):
    def OnInit(self):
        dlg = MyDialog()
        dlg.ShowModal()
        return False

if __name__ == "__main__":
    MyApp(0).MainLoop()

        thread.start_new_thread(
            lambda: CopyFilesThread(self),())

Hi - I think you just want to give start_new_thread() the function name and
the arguments to pass. The python language website describes the
start_new_thread function like this:

    start_new_thread( function, args[, kwargs] )

in which case it seems you want this instead:

    thread.start_new_thread( CopyFilesThread, self )

although I can't figure out how the results you are getting relate to the
code you have.

I hope this helps,
-Rick King

       thread.start_new_thread(
           lambda: CopyFilesThread(self),())

Hi - I think you just want to give start_new_thread() the function name and
the arguments to pass.

Better yet, ditch the thread module altogether and use threading.Thread instead. The threading module is higher-level than the thread module and is recommended for most purposes.

Jeff Shannon
Technician/Programmer
Credit International

Gerson Kurz wrote:

Another day, another problem. I have a progress dialog that is shown during
a lengthy operation (copying several files) in a background thread. The
thread communicates with the dialog with custom PyEvents, with a source
taken from the wxPython demo.

Everything works but: If, from the event callback, I try to do
wxDialog.EndDialog() the dialog closes, but ShowModal() never returns -> the
process never ends.

Here is an example that exhibits this behaviour. First three events are
generated (changing the title of the box), then a close event is posted. The
dialog is closed, but ShowModal() never returns.

If you let it set for a minute or so it eventually exits. I'll take a look and see if I can find out what is going on.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!