Re: Problem with threads

Robert Roebling <[email protected]> Fri, 29 Apr 2005 00:34:45 +0200
Newsgroups gmane.comp.lib.wxwindows.wxnet
Message-ID <[email protected]>
> Consider the following case:
> I create a window with a button inside.
> I create a thread that contains an endless loop which updates the button's 
> caption periodically.
> When I close the window, I get an exception (null pointer in wx-native code) 
> which is 100% correct because by the time I call the button.text (or 
> whatever), the button does not exist.
> 
> I know I have to stop the thread first but the problem is that I don't know 
> how to do it (WHERE to do it). I've tried the wx.Window.Closing event and it 
> didn't help. No luck with wx.Window.Dispose or destructor either. What is the 
> preffered way of postponing the window deletion until I'm finished with my 
> stuff?

What I do in C++

a) Define a new event which the thread sends to the 
   owning frame. Or just notify the window somehow
   that the thread has ended just so that it doesn't
   get deleted twice

DEFINE_EVENT_TYPE( wxEVT_THREAD_HAS_ENDED )

b) Here is your wxFrame. Note that the thread
   will send wxEVT_THREAD_HAS_ENDED either
   because it simply has finished doing something
   or after the thread has been stopped by the
   frame's close handler. In the later case, 
   m_deleteOnExit will be true and the frame
   will then be destroyed.

IMPLEMENT_CLASS(MyRecallFrame,wxFrame)

BEGIN_EVENT_TABLE(MyRecallFrame,wxFrame)
    EVT_COMMAND( -1, wxEVT_THREAD_HAS_ENDED,
                MyRecallFrame::OnThreadHasEnded )
END_EVENT_TABLE()

MyRecallFrame::MyRecallFrame( wxWindow *parent, wxWindowID id, const
wxString &title,
    const wxPoint &position, const wxSize& size, long style ) :
    wxFrame( parent, id, title, position, size, style )
{
    m_thread = NULL;
    m_deleteOnThreadExit = false;

    StartThread();
}

void MyRecallFrame::StartThread()
{
    m_thread = new MyRecallThread( this );
    m_thread->Create();
    m_thread->Run();
}

void MyRecallFrame::InterruptThread()
{
    if (m_thread)
        m_thread->Interrupt();
}

void MyRecallFrame::OnThreadHasEnded( wxCommandEvent &event )
{
    m_thread = NULL;
    
    if (m_deleteOnThreadExit)
        Destroy();
}

void MyRecallFrame::OnCloseWindow( wxCloseEvent &event )
{
    if (event.CanVeto())
    {
        if (m_thread)
        {
            m_thread->Interrupt();
            event.Veto();
            m_deleteOnThreadExit = true;
            return;
        }
    }
    
    Destroy();
}





-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix