Link to home
Start Free TrialLog in
Avatar of OD
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_cSocket))
 {
   // Exit the thread
 }
 else
 {
  CString strMessage = "Welcome...\n";
  pConnection->m_cSocket.Send(strMessage,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
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi OD,

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::PostThreadMessage() whose messagehandler then can call the ::PostQuitMessage() inside the thread.

hope that helps,

ZOPPO
ASKER CERTIFIED SOLUTION
Avatar of stefanr
stefanr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of OD
OD

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.

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.
Avatar of OD

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.