OD
asked on
Exiting CWinThread
Hi,
I am playing aroung with a multi threaded app and sockets and have the following situation...
I have a AsyncSocket in which I override OnAccept.
{
CConnectionThread *pConnection = new CConnectionThread();
pConnection->CreateThread( );
if (!Accept(pConnection->m_cS ocket))
{
// Exit the thread
}
else
{
CString strMessage = "Welcome...\n";
pConnection->m_cSocket.Sen d(strMessa ge,strlen( strMessage ));
delete(pConnection);
CloseHandle(pConnection->m _hThread);
}
where CConnectionThread is derived from CWinThread and m_cSocket is a CAsyncSocket member variable in CConnectionThread
The above works fine. All incoming connection request spawns this CConnectionThread and I receive the Welcome message
My problem is now that I can't seem to get these threads to exit in any way. I have tried calling ExitThread and _endthread, but they close the "listening thread" instead of the newly created client thread. I have tried delete(pConnection), but although it destroys the class, the thread still remains active. I have tried CloseHandle and other less applicaple options, nothing seems to work. The thread never closes.
Does anybody have an idea of how I can close (kill) the connection thread?
Thanx
I am playing aroung with a multi threaded app and sockets and have the following situation...
I have a AsyncSocket in which I override OnAccept.
{
CConnectionThread *pConnection = new CConnectionThread();
pConnection->CreateThread(
if (!Accept(pConnection->m_cS
{
// Exit the thread
}
else
{
CString strMessage = "Welcome...\n";
pConnection->m_cSocket.Sen
delete(pConnection);
CloseHandle(pConnection->m
}
where CConnectionThread is derived from CWinThread and m_cSocket is a CAsyncSocket member variable in CConnectionThread
The above works fine. All incoming connection request spawns this CConnectionThread and I receive the Welcome message
My problem is now that I can't seem to get these threads to exit in any way. I have tried calling ExitThread and _endthread, but they close the "listening thread" instead of the newly created client thread. I have tried delete(pConnection), but although it destroys the class, the thread still remains active. I have tried CloseHandle and other less applicaple options, nothing seems to work. The thread never closes.
Does anybody have an idea of how I can close (kill) the connection thread?
Thanx
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
If I terminate my CMyWinThread with
::AfxEndThread(0) (this code is definitately within the CWinThread class)
it terminates my application thread as well and my application (and all threads) terminate.
Why does that happen?
I also get an Assertion error on my Socket (member variable of the CMyWinThread class) when the thread terminates, any ideas?
I believe that you probably have answered my question, but if you can answer these additional ones I'll increase the points.
::AfxEndThread(0) (this code is definitately within the CWinThread class)
it terminates my application thread as well and my application (and all threads) terminate.
Why does that happen?
I also get an Assertion error on my Socket (member variable of the CMyWinThread class) when the thread terminates, any ideas?
I believe that you probably have answered my question, but if you can answer these additional ones I'll increase the points.
It looks like that ::AfxEndThread(0) is called from the primary thread, even if it is called from within the CWinThread class. That could happen if a member function that, directly or indirectly, calls ::AfxEndThread is called from the primary thread. You can verify which thread calls that function by using ::GetCurrentThreadId just before ::AfxEndThread and compare its return value with ::AfxGetApp()->m_nThreadId and pConnection->m_nThreadId.
The assert can occur when certain socket member functions is called from a thread other to which it is mapped (normally the thread that created the socket). In that case, it would be an ASSERT_VALID(this) that asserts. It can also occur when an outstanding socket event causes the callback function (OnReceive, et al) to be called when the socket object is already deleted/destroyed. It is quite tricky to avoid that situation in a multithreaded environment. One simple idea may be to call AsyncSelect(0), then sleep a while before calling delete.
The assert can occur when certain socket member functions is called from a thread other to which it is mapped (normally the thread that created the socket). In that case, it would be an ASSERT_VALID(this) that asserts. It can also occur when an outstanding socket event causes the callback function (OnReceive, et al) to be called when the socket object is already deleted/destroyed. It is quite tricky to avoid that situation in a multithreaded environment. One simple idea may be to call AsyncSelect(0), then sleep a while before calling delete.
ASKER
I eventually used the CSingleLock method described in the answer in InitInstance of the CMyWinThread. If the lock is attained false is returned and the thread exits.
The assertion error came from m_cSocket.Close in ExitInstance of this CMyWinThread class. I moved the code to OnClose of my socket, thus the code in CMySocket is:
void CMySocket::OnClose(int nErrorCode)
{
Close();
.....
That immediately sorted out the Assertion error, although I do not understand why it worked.
The assertion error came from m_cSocket.Close in ExitInstance of this CMyWinThread class. I moved the code to OnClose of my socket, thus the code in CMySocket is:
void CMySocket::OnClose(int nErrorCode)
{
Close();
.....
That immediately sorted out the Assertion error, although I do not understand why it worked.
This is from MSDN:
--------------------------
Normal Thread Termination
For a worker thread, normal thread termination is simple: Exit the controlling function and return a value that signifies the reason for termination. You can use either theAfxEndThread function or a return statement. Typically, 0 signifies successful completion, but that is up to you.
For a user-interface thread, the process is just as simple: from within the user-interface thread, call::PostQuitMessage in the Win32 Programmer’s Reference, Volume 4. The only parameter that ::PostQuitMessage takes is the exit code of the thread. As for worker threads, 0 typically signifies successful completion.
--------------------------
Because your using a CWinThread derived class you'll have to use the second method (for user-interface thread).
Now, I think best for this will be to send the thread a user defined message using CWinThread::PostThreadMess
hope that helps,
ZOPPO