Threads were not terminated by the application Topic is solved
you're making it sound more complicated than it is.
If your thread checks TestDestroy() every 10 seconds, than it takes 0-10 seconds to terminate it cleanly.
For that purpose to need to know when the thread actually terminates. You can use a thread list in your main thread like i described in the link i posted above.
http://forums.wxwidgets.org/viewtopic.php?p=96574#96574
Other options are sending an event, or just write into a variable in wxThread::Exit()
If your thread checks TestDestroy() every 10 seconds, than it takes 0-10 seconds to terminate it cleanly.
For that purpose to need to know when the thread actually terminates. You can use a thread list in your main thread like i described in the link i posted above.
http://forums.wxwidgets.org/viewtopic.php?p=96574#96574
Other options are sending an event, or just write into a variable in wxThread::Exit()
Use the source, Luke!
Because of this:neub wrote:I don't know how the main thread can wait the other threads to finish.
Code: Select all
MyFrame::~MyFrame()
{
myThread->Delete();
}
My 'maybe dirty' solution allows this. I'll give you a sample of code if you'ld like to (it's very very not complicated).neub wrote:So the last problem we have is when a thread sleep during like 10s, We need to wait at worst 10 seconds to go out the sleep and check the TestDestroy() method, then to delete object!
My question is if there is a way to cancel the this->Sleep(10000); to go check faster the TestDestroy().
Actually I'm using event and a list of threads > This works greats... Which is a pretty solution.
My code detached thread is actually like this
The only problem is that i need to wait about 10 seconds... but it could be about 1 minutes (Check if network connection is still responding)
I was wondering if we can cancel this->Sleep(10000); to make the detached thread destroy faster. Which means to close the application faster!
With this the pretty solution will be still valid, and the dirty hack make the main application close faster.
My code detached thread is actually like this
Code: Select all
void* Session::Entry() {
while(!this->TestDestroy()) {
...
this->Sleep(10000);
}
}
I was wondering if we can cancel this->Sleep(10000); to make the detached thread destroy faster. Which means to close the application faster!
With this the pretty solution will be still valid, and the dirty hack make the main application close faster.
Here it is - by the way, this code can be criticize.
myThread.cpp
That's all folks.
So thread is polled every 500 milliseconds, but real work is done every 10 seconds (merely in fact, depends on /* thread work */)
myThread.cpp
Code: Select all
myThread::myThread()
: wxThread(wxTHREAD_DETACHED)
{
this->pollTime = 500;
this->runTime = 10000; // sleeps for 10 seconds
}
void* myThread::Entry()
{
size_t countdown = 0; // initializes countdown (ensures actions will be executed right at thread start)
while ( !this->TestDestroy() ) { // while observation is active
if ( countdown <= 0 ) {
/*
thread work
*/
countdown = this->runTime - this->pollTime; // resets countdown
}
else { // if countdown has not expired (keeps sleeping until next run)
countdown -= this->pollTime; // decrements countdown
}
this->Sleep(this->pollTime); // sleeps until next scan
}
}
So thread is polled every 500 milliseconds, but real work is done every 10 seconds (merely in fact, depends on /* thread work */)
At first, this is what i did. But a combination of different problems made me code this polltime/runtime solution.doublemax wrote:If your thread checks TestDestroy() every 10 seconds, than it takes 0-10 seconds to terminate it cleanly.
- if application was in systray, and click quit on systray menu, application has to deiconize so relevant size and position values could be retrieved
- deiconizing the application when quitting didn't hide frame while waiting for threads to delete
wxNapThread class
Hello guy,
here is the result of our long discussion.
I've implemented a generic class derived from wxThread called the wxNapThread.
It ease the way to:
- Use pollTime and runTime with a Nap() function similar to Sleep().
- Send custom event (wxEVT_THREAD) when the wxThread is terminated.
- Connect easyly to an wxEvtHandler.
-
If you have suggestion to improve it i'm okay with this.
here is the result of our long discussion.
I've implemented a generic class derived from wxThread called the wxNapThread.
It ease the way to:
- Use pollTime and runTime with a Nap() function similar to Sleep().
- Send custom event (wxEVT_THREAD) when the wxThread is terminated.
- Connect easyly to an wxEvtHandler.
-
If you have suggestion to improve it i'm okay with this.
Code: Select all
#ifndef WXNAPTHREAD_HPP_
#define WXNAPTHREAD_HPP_
#include <wx/wx.h>
#include <wx/event.h>
#include <wx/thread.h>
//! Define the event type wxEVT_THREAD for all the thread used.
extern const wxEventType wxEVT_THREAD;
#define EVT_THREAD_TERMINATED 0
#define THREAD_RET_OK 0
#define THREAD_RET_DELETED -1
#define THREAD_RET_ERR_INIT -2
/**
* @brief The wxNapThread is an abstract class representing a detached threads with
* additional options.
*
* The wxNapThread use a two timers:
* - one for sleeping (pollTime).
* - one for taking a nap (napTime).
*
* At each loop the thread Sleep() during pollTime to avoid consuming CPU. At each pollTime the
* thread looks if it need to be paused, resumed or deleted.
*
* Moreover, If the user don't need to use so much the thread (i.e, each 10 seconds) the user
* can make the thread taking a nap (doing nothing) during napTime using the function Nap().
* In other words, during the napTime the function never go inside the function Loop().
*
* This let the user delete the script in at worst pollTime, even if the thread is doing
* nothing during napTime.
*
* @note This class is still abstract, therefore Entry() function still need to be defined
* in a derived class
*
*
* @ingroup net
*/
class wxNapThread : public wxThread {
public:
wxNapThread(wxEvtHandler* pParent,int PollTime=50);
virtual ~wxNapThread();
virtual wxThreadError RunResume();
void Nap(unsigned long milliseconds);
void WakeUp();
protected:
virtual void OnExit();
void SendEvt(const wxCommandEvent &evt);
void Connect(wxObjectEventFunction func);
private:
wxEvtHandler *m_pParent; //!< Pointer on a class derived from wxEventHandler.
int m_pollTime; //!< pollTime set a initialization
int m_napTime; //!< Set while calling nap
int m_countDown; //!< countDown (can be reset by WakeUp())
int m_retCode;
};
#endif /* WXNAPTHREAD_HPP_ */
Code: Select all
#include "wxNapThread.hpp"
DEFINE_EVENT_TYPE(wxEVT_THREAD)
/**
* This constructor creates a new detached C++ thread object with nap and event functions.
*
* @param pParent a wxWidget object which is derived from wxEvtHandler (@ref wxWindow).
* @param pollTime the minimum Sleep() time of this thread, if it is equal to zeros the
* thread will consume 100% of the CPU because it will never pause.
*/
wxNapThread::wxNapThread(wxEvtHandler* pParent, int pollTime)
: wxThread(wxTHREAD_DETACHED), m_pParent(pParent), m_retCode(0),
m_pollTime(pollTime), m_napTime(pollTime), m_countDown(0)
{
if(pollTime<0) {
this->m_pollTime=10;
this->m_napTime=10;
}
}
/**
* @brief Default destructor.
*/
wxNapThread::~wxNapThread() {
}
/**
* @brief Create, Resume or Run the threads depending on the actual state of the threads.
* @see wxThread::Create(), wxThread::Resume(), wxThread::Run().
*/
wxThreadError wxNapThread::RunResume() {
wxThreadError err;
//If the thread is in pause make it run again.
if(this->IsPaused()) {
this->WakeUp();
return this->Resume();
}
//If the thread is running put it in pause.
else if(this->IsRunning()) {
this->WakeUp();
return this->Pause();
}
//Otherwise the thread is not created (neither running nor paused)
else {
err = this->Create();
if(err=!wxTHREAD_NO_ERROR) return err;
err=this->Run();
return err;
}
return wxTHREAD_NO_ERROR;
}
/**
* @brief Pauses the thread execution for the given amount of time,
* but let us waking up from this pause.
* @note This function is similar to wxThread::Sleep(), however during
* the Sleep() the thread is not usable (Delete(), Pause(), Run()).
*
* Using Nap() permits to let the thread doing nothing but polling
* if an action must be done during the nap time.
*
* @see http://wxforum.shadonet.com/viewtopic.php?p=98722
*
*/
void wxNapThread::Nap(unsigned long milliseconds) {
//Set the napTime if it is greater than pollTime.
if(m_pollTime<milliseconds) {
m_napTime=milliseconds;
m_countDown = m_napTime - m_pollTime;
while(!(this->TestDestroy())) { // while observation is active
if ( m_countDown <= 0 ) {
break; //or exit the loop!
}
else { // if countdown has not expired (keeps sleeping until next run)
m_countDown -= m_pollTime; // decrements countdown
}
//Truely sleep the thread (can not delete it during this time).
this->Sleep(m_pollTime);
}
}
else {
this->Sleep(m_pollTime);
}
}
/**
* @brief Wake up the thread while is taking a nap but not while is sleeping.
*/
void wxNapThread::WakeUp() {
m_countDown=0;
m_napTime=m_pollTime;
}
/**
* @brief Send EVT_THREAD_TERMINATED when the thread is terminated.
* @note To know the exit code of the thread we can use evt.GetInt().
*/
void wxNapThread::OnExit() {
wxCommandEvent evt(wxEVT_THREAD, EVT_THREAD_TERMINATED);
evt.SetInt(m_retCode);
this->SendEvt(evt);
}
/**
* @brief Send an event to the Event Handler.
* @note Don't forget to connect the event handler to this class.
* @see Connect().
*/
void wxNapThread::SendEvt(const wxCommandEvent& evt) {
m_pParent->AddPendingEvent((wxEvent&)evt);
}
/**
* @brief To connect the eventHandler function to this thread we need to use this Connect function.
*
* In the event handler, if the function is something like this
* @code
* void EvtHandlerClass::OnThreadEvt(wxCommandEvent& evt) {
* switch(evt.GetId()) {
* case EVT_THREAD_TERMINATED:
* ...
* break;
* ...
* default:
* ...
* break;
* }
* }
* @encode
*
* Then, we need to call this->Connect(wxCommandEventHandler(EvtHandlerClass::OnThreadEvt));
*/
void wxNapThread::Connect(wxObjectEventFunction func) {
m_pParent->Connect(wxEVT_THREAD,func,m_pParent);
}