The article directories
-
- One, foreword
- Second, the quotes
-
- 1. Case Description
- 2. Case realization
- Third, problem analysis
-
- A, output,
- Second, the analysis
- Iv. Improvement plan
One, foreword
- This article describes a case where the main thread actively deletes child thread objects, causing the main thread to freeze (infinite wait).
Second, the quotes
1. Case Description
- 1) The implementation includes a main thread and a child thread;
- 2) The main thread is responsible for starting the child thread and destroying it after the child thread runs for 500ms:
- 3) The sub-thread outputs a keepalive message every 16ms;
2. Case realization
- Child Thread LogicThread inherits Thread (Thread class implementation reference);
#include "Thread.h"
class LogicThread : public Thread
{
public:
LogicThread() : m_bStop(false) {}protected:
virtual void DoWork(a) {
while(! m_bStop) {printf("Thread[%d]: I'm active! \n", GetId());
Sleep(16);
}
printf("Thread[%d]: I'm exit! \n", GetId());
}
private:
bool m_bStop;
};
int main(a) {
LogicThread *pLS = new LogicThread;
pLS->Start();
Sleep(500);
delete pLS;
return 0;
}
Copy the code
- Does the delete of this code run smoothly? The answer is no!
Third, problem analysis
A, output,
- I’m active! I’m active! :
Thread[70508]: I'm active!
Thread[70508]: I'm active!
Thread[70508]: I'm active!
Thread[70508]: I'm active!
Thread[70508]: I'm active!
Thread[70508]: I'm active! .Copy the code
Second, the analysis
- The breakthrough point of analysis is the call of DELETE;
- If there is no delete, then the main thread can go to return 0;
- When delete is added, the destructor of the base Thread is called, and the Stop() interface of the child Thread is called as follows:
Thread::~Thread() {
Stop();
}
void Thread::Stop(a) {
if(! m_pkHandle) {return;
}
WaitForSingleObject((HANDLE)m_pkHandle, INFINITE);
CloseHandle((HANDLE)m_pkHandle);
m_pkHandle = NULL;
}
Copy the code
- Because the child thread is running and not returning, WaitForSingleObject blocks and waits. This call is made on the main thread, so the main thread is dead.
Iv. Improvement plan
- To keep the WaitForSingleObject from waiting indefinitely, you need to ensure that the thread function exits before the logical thread is destroyed.
- Therefore, the state of the child thread can be polled in the main thread, and the exit logic can be executed when the child thread enters the exit state.
- To clarify the problem, add a thread termination condition, set m_bStop to true when the counter 100 is finished.
#include "Thread.h"
class LogicThread : public Thread
{
public:
LogicThread() : m_bStop(false) {}protected:
virtual void DoWork(a) {
int nCnt = 100;
while(! m_bStop) {printf("Thread[%d]: I'm active! \n", GetId());
Sleep(16);
if (--nCnt == 0) {
m_bStop = true; // Add the end condition}}printf("Thread[%d]: I'm exit! \n", GetId());
}
private:
bool m_bStop;
};
int main(a) {
LogicThread *pLS = new LogicThread;
pLS->Start();
// The main thread waits for the child thread to exit;
do {
Sleep(16);
} while (pLS->IsRunning());
// Clear up thread information
delete pLS;
return 0;
}
Copy the code