Click here to Skip to main content
Click here to Skip to main content

Using User-Interface Threads

By , 16 May 2000
 

Introduction

I've never done a user-interface thread that has windows or controls. On the other hand, the complement of a worker thread is not necessarily a thread that has user-interface objects. The complement of a worker thread is a thread that has a message pump. This is a subtle but important distinction, but one that I have either needed or exploited, depending on circumstances.


Apartment Threading

I don't pretend to be an expert on "apartment threading".  I fell into it because I needed to know a small number of things about it, specifically, how to get an SAPI-enabled application to run.

The key to "Apartment threading" is that an object which is initialized should be initialized in a particular thread and all operations on that object must be performed from that same thread. Trying to do operations on the same object from other threads is not guaranteed to work correctly. The point of this being that the object can be then written without worrying about incorporating thread-safe operations, because only one thread ever accesses it.


The Message Pump

What I needed to run SAPI in a separate thread was not a worker thread, but a thread with a message pump. The thread does not have to have GUI objects, and hence the name "User-Interface Thread" is a serious misnomer. The user interface may not even be relevant.

What SAPI requires is a message pump. So I had to start a "user-interface" thread. There were a couple problems, so this essay tries to capture my experience.


Creating a User-Interface Thread

First, there is the question about how to create the thread. What you first need is a CWinThread-derived class, which is then necessarily a CCmdTarget-derived object. Use the ClassWizard to create it, and you will get all the correct declarations. For purposes of this essay, it will be called CMyThread.

Now, you would expect to use AfxBeginThread, in the approved fashion, doing

CMyThread * thread = AfxBeginThread(RUNTIME_CLASS(CMyThread));

Well, it isn't quite that easy. It should be, but it isn't. What's missing here is a way to pass initial parameters in to the thread! 

Consider a couple cases: you don't have a CMyThread object until the AfxBeginThread completes. But by the time you get control, the thread may already be running, and therefore it may be too late to set any values.

There are a couple solutions to this. One is to create the thread suspended, by providing the CREATE_SUSPENDED flag. Note that because this does not default we have to provide the intermediate parameters, the thread priority and the call stack size, so provide the values which are the defaults:

CMyThread * thread = AfxBeginThread(RUNTIME_CLASS(CMyThread),
                                    THREAD_PRIORITY_NORMAL,
                                    0, // stack size
                                    CREATE_SUSPENDED);

And upon completion, you can then set any member variables in the class, and explicitly resume the thread:

thread->m_Whatever = ...;
thread->m_OtherThing = ...;
thread->ResumeThread();

I chose to do the two-step method suggested in the AfxBeginThread documentation:

CMyThread * thread = new CMyThread();
thread->m_Whatever = ...;
thread->m_OtherThing = ...;
thread->CreateThread();

I did this just because I did not like to explicitly specify the defaults.


The Thread Function

OK, you've already done worker threads. You know that you provide a function that is called to execute the thread body, and the thread terminates when this function terminates, the thread ends. But what about a user-interface thread? Where is your function?

The answer is that it is CWinThread::Run is the thread function. This is the message pump. When it exits, your thread terminates.


Using the Thread Function

The key methods you might be interested in are virtual methods of your class. You can create these using ClassWizard:

BOOL PreTranlsateMessage(LPMSG msg) allows you to process messages before letting them be handled by the usual message dispatch. If you process the message at this point and do not want it dispatched, you must return TRUE. If you have processed it and want normal processing to continue for it, or you don't want to process it yourself, you return FALSE.

BOOL OnIdle(LONG count) is called as long as you have "idle tasks" to do and there are no other messages. The first time it is called for idle processing the count is 1, and the count is incremented on each subsequent call. If you return TRUE you will be called again, and again, until you return FALSE. Any time there is a new message to be processed, the counter is reset to 0. If you return FALSE, the message loop blocks until a message comes in.

BOOL InitInstance() is where you can do any setup for your class. For example, this is where I call CoInitialize(NULL) to initialize the COM subsystem to support the SAPI objects I'm calling. Note that CoInitialize is thread-specific and must be called for each thread that is calling ActiveX objects. If InitInstance fails, you should return FALSE. This will cause the thread to terminate.

void ExitInstance() is where you do any cleanup for your class. It is called after the message pump terminates. This is where I do CoUninitialize() to clean up the COM resources allocated for the thread.

BOOL PostThreadMessage(UINT msg, WPARAM wParam, LPARAM lParam) allows you to post a message to the thread. It returns TRUE if successful and FALSE if error.


Using the Message Map

The Message Map for a CWinThread does not support all messages, although it won't complain if you try to put something unsuitable in it. You need to use the macros

ON_THREAD_MESSAGE(UINT msg, LRESULT (handler *)(WPARAM, LPARAM))
ON_REGISTERED_THREAD_MESSAGE(UINT msg, LRESULT (handler *)(WPARAM, LPARAM))

The ON_THREAD_MESSAGE macro requires that the msg parameter be a constant, typically a (WM_APP+n) value. The ON_REGISTERED_THREAD_MESSAGE macro requires that the msg parameter be the name of a UINT variable that holds the Registered Window Message. If you need to understand more about how to form these messages, read my essay on Message Management.

The message handler is a function whose signature is as shown. The WPARAM and LPARAM of the PostThreadMessage are passed to the handler method. The return value is always ignored, and is traditionally 0.


General Queuing

You can queue messages up for processing simply by using PostThreadMessage. You don't need a queue, interlocks, or any other mechanism to handle queuing. However, because you are doing PostThreadMessage, you must make sure that the object you are passing is still in existence at the time you process the message. This means that if you are not passing simple integer values as WPARAM or LPARAM, for example, if you want to pass a CString, you must pass a pointer to an object on the heap and delete it when you've processed the message. You cannot pass a pointer to anything on the stack.

However, this also suggests that a "user-interface" thread can also be thought of as a "queued event thread", where you use PostThreadMessage to add entries to the queue, and dispatch the dequeuing via the MESSAGE_MAP.


Terminating the loop

So we know how to start the thread, and initialize the thread, but how do we stop the thread? Just like any other message pump, as it turns out. Just post a WM_QUIT message. It is unfortunate that Microsoft has not chosen to be consistent, but they actually require in the PostThreadMessage that you explicitly provide the WPARAM and LPARAM values, which are, in this case, 0. So when you get to the point where you are read to shut down the thread, just do

thread->PostThreadMessage(WM_QUIT, 0, 0);

and the thread shuts down.


Hazards

It is a bad idea to mix thread control using PostThreadMessage and UI objects such as message boxes and dialog boxes. When a thread message is received by GetMessage, it has a NULL window handle. This means that it cannot be dispatched via DispatchMessage. Special handling is required for thread messages, which is built into the message pump of CWinThread::Run. What this means is that if you call DoModal or AfxMessageBox, MessageBox, or any similar function that spawns a new message loop any posted thread messages will be lost. Microsoft suggests using a message hook function to intercept messages under these conditions. Consequently, if you are going to use PostThreadMessage to a UI thread, you should follow the advice given in my essay about worker threads and treat the UI thread as if it were a worker thread insofar as spawning child dialogs.


The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to newcomer@flounder.com with questions or comments about this article.
Copyright © 1999 <!--webbot bot="Substitution" s-variable="CompanyLongName" startspan -->The Joseph M. Newcomer Co.<!--webbot bot="Substitution" endspan i-checksum="64444" --> All Rights Reserved.
www.flounder.com/mvp_tips.htm

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Joseph M. Newcomer

United States United States
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionWhat king of thread should I use?memberJulian Popov8-Mar-08 6:46 
Hello
 
I want to write some king of mail client application. I want to have a 2-nd thread which have to do all the logn work.
 
I use:
1) MFC Internet classes and
2) A library for "signing a messages".
 
I want to send commands to 2-nd thread to send or receive a messages, also to check my inbox (OnTimer).
 
There is a case when 2-nd thread need to interact through a dialog box with a user.
Some of this interacts are handled by me (and can be done from Main thread), but some of them are shown automatically from a "signing messages library".
 
Can I create my MFC Internet and signing library objects from 1-st thread and pass them to 2-nd thread safe?
Is there a problem if signing library show it's own dialog box?
Can I use worker thread instead of UI thread?
 
Thank you very much in advance
Julian
 
??????????????????????????????

AnswerRe: What king of thread should I use?memberJoseph M. Newcomer8-Mar-08 18:25 
In theory, you can use the kind of thread you want, but in practice, you have to use the kind of thread you need.
 
I'm serious. That is the best answer that can be given. For example, if your secondary thread is using CAsyncSocket, it *must* be a UI thread, no option possible. Socket systems like CAsyncSocket require a UI thread to pump the notification messages.
 
I disapprove of the concept of secondary threads interacting with the user. Logon credentials can be obtained before the secondary thread is started. If anything goes wrong, the thread should probably terminate anyway. For example, if the logon fails. Just say the logon failed, by posting a message to your main GUI thread. Go back to the secondary thread's message pump and wait for something to happen. If the user types a new set of login credentials, eventually a message will come by that says "try login". If the user clicks "cancel", a message will come by that says "quit the thread". A library in a secondary thread should not be popping up random dialogs; it should be returning error codes. It can support an entry point which, when passed some error packet returned from a previous call, will pop up a dialog; then you would post a message to the main GUI thread asking it to display the dialog, and return to the secondary thread's message pump. Eventually, it receives a notification to "continue with accepted certificate" message (which might contain the information posted to the main GUI thread) or a "certificate rejected" message. Key here is stop thinking of the secondary thread as having any possibility of user interaction, and refactor your code so this is not necessary.
 
See my essay on UI threads on my MVP Tips site.
GeneralUI thread without ui interface is a better "worker thread" when need message pumpmemberhamo200822-Oct-07 20:36 
Great!
 
UI thread without ui interface is a better "worker thread" when need message pump.
 
http://www.ucosoft.com
----
You have noting to lost, but everything to gain.

GeneralRe: UI thread without ui interface is a better "worker thread" when need message pumpmemberJoseph M. Newcomer24-Oct-07 12:38 
A UI thread wihtout visible windows is still a UI thread; this naming is poorly chosen. I prefer to refer to it as "a worker thread with a message pump" if I want to be pedantic, but formally within MFC a worker thread with a message pump is called a "UI Thread", and we have to stick with the names that Microsoft invented, however inappropriate they actually are.
QuestionTerminating a thread...memberSalvatore Castellano17-May-06 5:45 
Suppose one uses a UI thread, which is created within OnInitDialog (of the 'main' dialog application) through dynamic allocation, and you wish to terminate it when the main dialog closes (and app quits).
 
I understood one should use the PostThreadMessage(WM_QUIT, 0, 0); however, right after the thread was stopped, memory leaks reported, which in fact make sense. Before the UI thread had the time to process the WM_QUIT message, the main application was perhaps already gone...
 
Does anybody know what the correct is to terminate the UI thread and then close the main dialog?

Example:

 
// not really relevant where the creation takes place
...
CMyThread *thread = new CMyThread();
thread->CreateThread();

...
 
void CMainDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CDialog::OnSysCommand(nID, lParam);
if (nID == SC_CLOSE)
{
thread->PostThreadMessage(WM_QUIT, 0, 0); // kill UI thread
PostMessage(WM_QUIT); // terminate main app
}
}

 
Salva
AnswerRe: Terminating a thread...memberLuca Piccarreta19-Jun-06 8:46 
I think you should Wait for the thread termination....
The Windows API is "WaitForSingleObject"
But Actually I don't know how the API is mapped in the
MFC thread class.
Moreover, it is not such a rare case that you incur in
deadlocks!
As a matter of fact, deadlock (or critical races) will happen if
the child thread will use some form of SendMessage to windows
owned by the father thread.
Luca.

GeneralGive us an example!memberKybert18-Apr-06 22:34 
Do you have an example that simply moves a progress bar up and down so i can see how to impliment the addition of a control into the GUI thread?
GeneralRe: Give us an example!memberJoseph M. Newcomer19-Apr-06 3:06 
No, because this would be inappropriate. My belief is that a UI thread would *never* manipulate a control in the user interface, because that is the responsibility of the main GUI thread. See my essay on worker threads here in CodeProject. The problems arise because a child control, such as a progress bar, must be owned by the main GUI thread, and therefore cannot be manipulated by any other thread. So this would not be the correct approach. Instead, whether you are making your progress in a UI thread or non-UI thread, you would always PostMessage the update request to the main GUI thread and let it do the update. Do *NOT* try to manipulate any control owned by the main GUI thread from a UI thread, and do not create, in a UI thread, any child control whose parent is owned by another thread.
GeneralMutlipule threadsmemberTom Wright6-Oct-04 6:58 
So if I wanted to create a certain number of threads would I do this:
 

CMyThread* thread[] = new CMyThread();
 
and to kill the one of the threads I would do this:
 
thread[2]->PostThreadMessage(WM_QUIT, 0, 0);
Is this right?

 
Tom Wright
tawright915@yahoo.com
GeneralRe: Mutlipule threadsmemberJoseph M. Newcomer12-Oct-04 19:01 
For UI threads, there are two ways of doing it. new CMyThread simply creates the thread object; you must then do a Create on the thread object to get an actual thread. All you have after the new is a CMyThread object with no actual running thread. More likely you would do
 
CMyThread * thread[i] = (CMyThread *)AfxBeginThread(RUNTIME_CLASS(CMyThread), ....etc ...);
 
which creates the object and creates a thread to go with it.
joe
 

GeneralWM_TIMER in UI Threadmembersudiptam4-Oct-04 20:28 
Your article regarding the UI thread is really helpfull . But I have some problems . Can a UI thread be associated with any UI objects ? Suppose I want to post a WM_TIMER message associated with a window to a UI thread's message queue .
You can reply me at aveek_99@yahoo.com.
 
Please help ......
GeneralRe: WM_TIMER in UI ThreadmemberThatsAlok27-Jul-07 0:20 
sudiptam wrote:
Can a UI thread be associated with any UI objects ?

 
no,it is advisable not to do that!
 
sudiptam wrote:
Suppose I want to post a WM_TIMER message associated with a window to a UI thread's message queue .

 
what method do you use to post message. i.e. SendMessage or PostMessage
 

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow


cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief

GeneralSockets MultithreadingmemberAshutoshSolanki20-Jul-04 20:52 
I am trying to develop an application which creates a UI thread when the listening socket accepts a new connection. The sequence is as follows
 
1.Accept the connection in CAsyscsocket object
2.Detach the accepted socket and assign to CwinThread derived class's SOCKET member.
3.Resume Thread
4. In the InitInstance attach the local AsyncSocket Member to the SOCKET..
 
All this is working fine.. But my thread is not receiving any data.. Or may be I dont know the correct procedure from here on..
How do I receive the data in Thread
Plz. help..

Generalocx with a non-modal dialogmemberconchi26-Mar-04 2:27 
Hello, Joseph. I'm a newby in Visual C programming I read your very useful article and I have a doubt.
 
I have programmed a ActiveX control that implements a non-modal dialog.
First, I tried with a CreateWindow()to create the dialog inside the OCX and that works, but
my dialog does not capture any keypressed. Seems as if the PreTranslateMessage()of the dialog does not execute never. The key presed are going to the parent of the dialog, but this was not the Ctrl of the OCX, it seems to be the application demo where you insert the OCX.
 
So, I tried to do an CWinThread with a modal dialog inside (with DoModal()) and it seems to work prefectly since now. The modal dialog capture keys and from the methods of the ActiveX I send PostThreadMessages to the WinThread. But you don't recommend this.
 
can you give any advice of how making this in the best way?
 

 
Sorry for my bad English . I hope that you will be able to understand me.
 
Thanks
 
,
GeneralRe: ocx with a non-modal dialogmemberJoseph M. Newcomer26-Mar-04 4:39 
I don't do ActiveX. However, CreateWindow would be incorrect...did you mean CreateDialog?
 
If a modeless dialog is active, the hosting app has to call IsDialogMessage(dlg) to pass all messages to the modeless dialog.
 
Do NOT use PostThreadMessage to send messages to anything that has GUI components. If you should pop up a MessageBox, the message will be lost. Use PostMessage to the window.
 
If the dialog has a parent, putting in a separate thread is extremely risky.
 
But since I don't do ActiveX, I don't have any insights on why this actually fails or how it could be made to work.
GeneralRe: ocx with a non-modal dialogmemberconchi28-Mar-04 20:35 
Thanks very much for your quick response.
 
I meant CreateDialog() of course, sorry.
Don't worry about OCXs. Look this scenario:
 
You have two CWinThreads one of them with a modal dialog and the other one without window. How do you pass messages between them in a safely way?
 
Now we use for this Registered Messages and using a hook SetWindowsHookEx(WH_GETMESSAGE....);
Aparentely in this way there is not lost messages, but we don't know if this is the best way.
 

Thank you very much.

GeneralRe: ocx with a non-modal dialogmemberJoseph M. Newcomer28-Mar-04 20:58 
I presume that the "other" thread is a UI thread. In that case, you have a message map, so you read my essay on interthread messaging, and out an
ON_THREAD_MESSAGE
or
ON_REGISTERED_THREAD_MESSAGE
handler in the receiving thread, and do PostThreadMessage from your main GUI thread to the worker thread. Or you read my essay, and use PostMessage to post a user-defined message from a worker thread to your main UI thread, and do an
ON_MESSAGE
or
ON_REGISTERED_MESSAGE
handler in the message map of the receiving window. There is no reason to even consider a hook as part of the solution. In fact, it is probably a very bad way.
GeneralRe: ocx with a non-modal dialogmemberconchi28-Mar-04 21:40 
I have read the Messages Management essay from you but I have some doubts.
 
It seems that I can't explain the problem correctly (bad english). I will try again.
 
I have one CWinThread with a modaless dialog and this thread creates another CWinThread with a window (not a dialog, but it does not matter). We call them Thread1 the main thread, Thread2 the second thread. There are not worker threads.
Sometimes (not always), if I make PostThreadMessage() from Thread2 to Thread1 the message is lost.
 
Really, the PostThreadMessage() does not return any error, so it seems to be sent. But Thread1 does not receive it. We can see with the Spy++ that the message does not received.
I do this with registered messages and without them (with ON_MESSAGE) and the problem is the same
 
Instead of this, if I make a hook in Thread1 the problem seems to be solved.
 

Thanks.

GeneralThread TerminationmemberAcreff26-Jan-04 9:32 
I wish to terminate the UI thread but I do not wish to use the WM_QUIT message. The reason is that I would like to do some clean up in the thread to avoid memory leaks. To the best of my knowledge WM_QUIT will quit unconditionally, right. Which is best approach to a situation like this one ?
GeneralRe: Thread TerminationmemberAcreff26-Jan-04 11:52 
I think I am getting closer to a solution. Please correct me is I am on the wrong track. The way I am dealing with the situation is to post a message to the thread, process it in PreTranslate and prepare the thread for shutdown by doing some cleaning. I have however the following problem.
 
I am using the WaitForSingleObject for waiting the thread to finish before proceeding (e.g. to exit the application) in a similar way that Joseph has explained in his "Working Threads" article. After some reading in the MSDN I found that if the CoInitialize function is used in the thread (which is true in my case) then the WaitForSingleObject is not suitable for the task and that I should use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
 
However I could not find anything that will help me use the MsgWaitForMultipleObjects.
 
I would appreciate (first of all) some one to tell me if I am on the correct track and if so, how to use the MsgWaitForMultipleObjects
 

Thank you in advance
 
Pothitos M. Baikas
GeneralRe: Thread TerminationmemberJoseph M. Newcomer27-Jan-04 0:17 
You are definitely on the wrong track! This is a horrible misuse of PreTranslateMessage. I can't imagine why this would make more sense than simply adding a message handler in the message map! That's what message maps are for.
 
First rule of using PreTranslateMessage: you are almost certainly wrong.
Second rule of using PretranslateMessage: if you still think you need it, you are still wrong.
Third rule of using PreTranslateMessage: maybe, just maybe, it makes sense. But probably not.
Fourth rule of using PreTranslateMessage: there is a slight chance you are right.
 
You have fallen into the first rule. It makes no sense.
 
In cases where you think you need to wait for a thread to finish, it often makes more sense to simply have the thread send a notification of its completion to the main GUI thread, and not wait at all. As long as you don't set the m_bAutoDelete to FALSE, everything works fine. Saves all possible hassles of bizarre solutions involving MsgWaitForMultipleObjects. Just kill the thread and go away. When you receive the notification of the thread completion via the PostMessage to your main GUI thread, you enable anything that you had disabled, etc.
GeneralRe: Thread TerminationmemberAcreff27-Jan-04 4:24 
OK then. I am totally on the wrong track. Let's just confirm it (and let's hope that some one will find a couple of minutes to explain what is wrong). That's what I am doing:
 
-I have created a CWinThread object using ClassWizard.
-All my code for the thread is in the Run() function.
-I declare a volatile BOOL as m_bContinueRunning and I initialise it to TRUE as soon as the thread begins its execution.
-In the main loop of the thread, I check this variable and if it continues to be TRUE the thread continues running.
-In the calling thread now, I at some point in time decide that I would like the thread to be notified that it should stop running (more specifically in the OnClose() of my MainFrame.
-I then check if the thread is still running, and I set the threads m_bAutoDelete to FALSE.
-I then post a message to the thread (MyThread->PostThreadMessage(WM_TERMINATE_THREAD_MESSAGE, 0 , 0))
-and tell the calling thread to wait till MyThread ends :
result = WaitForSingleObject(MyThread->m_hThread, INFINITE)
-When this happens (theoretically) I delete MyThread (MyThread->Delete())
-From the point of MyThread now. I process the message sent by the calling thread with ON_THREAD_MESSAGE(WM_TERMINATE_THREAD_MESSAGE,OnTerminate). (I stopped using the Pretranslate as Joseph indicated)
-In OnTerminate I change the variable m_bContinueRunning to FALSE (I have checked that and it works)
-At this point I expect (perhaps wrongly) for the thread's loop to see that the variable has turned to FALSE (since I check it continuously), start the clean-up and then exit.
-Furthermore I would expect the main application thread to continue from the point it has stopped and waited and continue with the deletion of the thread and then gracefully close the application.
 

The approach above does not work.
-The variable is never checked
-The calling thread just not waits for my thread to finish (by the way the result code from WaitForSingleObject is 0)...
-and since I am checking in the OnClose(), it continues and exit the main application thread.
Further more MyThread continues running, even if the main application thread has exited (and I get a lot of memory leaks that do not appear if the application exits with MyThread NOT running.
 
I know that I am doing something wrong (easy to understand isn't it ???)
I also know that Joseph will start yelling at me that no matter how much time he has spent explaining everything, I am too thick-headed to understand (Joseph, I am only joking..) but I still cannot find the error.
 
I only hope that someone will find the time to help me a little bit on this
 
Warm regards

GeneralRe: Thread TerminationmemberJoseph M. Newcomer27-Jan-04 8:08 
Yes, several things wrong here.
 
First, don't touch the Run() function. If you have a UI thread, the purpose is to be able to handle messages. So you let the default Run() function run. I have never written a Run() function for any thread, because there is no need to.
 
Initializing the run value to TRUE as soon as the thread starts running is much too late; the thread that created this thread could have already set it to FALSE, and therefore you would never terminate.
 
You have defeated the entire purpose of UI threads, which is to have a message pump. You should be using a worker thread.
 
Cleanup as you describe should be done in ExitInstance.
 
The way I handle close in this case is what I don't set m_bAutoDelete to FALSE, but just let the thread delete itself. The OnClose handler consists of setting the thread boolean to FALSE and returning (and not calling the superclass OnClose() handler, which would close the app). When I get the notification message from the thread that it has completed, I respond to that message by calling my superclass OnClose() and letting the close proceed normally.
 
Key question: why do you think you need a UI thread? (There are lots of good reasons, but by building one in which you do all the work in Run() you have defeated most of the advantages of doing so). Note that if you need a UI thread to handle sockets, SAPI, or something like that, putting other computations there is probably a bad idea.
GeneralRe: Thread TerminationmemberAcreff3-Feb-04 6:52 
Reading through these messages, I realised that you are right. The UI thread is not the way to go (for my purposes). Keeping that in mind, I re-read both articles and my code is in a much better shape. Thanks for your time.
 
Regards
GeneralRe: Thread TerminationmemberJoseph M. Newcomer26-Jan-04 14:12 
Yes, but control then goes to the ExitInstance handler, which can do any cleanup. Or, you can PostThreadMessage to it a UWM_CLEAN_STUFF_UP message of your own, which does the cleanup and then does a PostQuitMessage.
GeneralTerminating Threadsmemberbgsewell25-Aug-03 11:10 
I am trying to write a package that allows multiple TCP/IP connections. In some cases, the local machine is the server, but at the same time, the local machine may also connect as a client to another machine. I want each of the connections to run in its own thread. I am creating a user interface thread using AfxBeginThread for each connection. I have a class, MyConnection, which inherits from CWinThread and represents a single TCP/IP connection. I want to terminate the thread and delete the instance of MyConnection when the connection is closed. A couple of questions...
1. When the instance of MyConnection is destroyed, does the thread automatically terminate?
2. The CAsyncSocket::AssertValid always fails. Any ideas why?
 
Thanks for any comments!
 
brenda
GeneralRe: Terminating ThreadsmemberJoseph M. Newcomer25-Aug-03 11:24 
1. Unless you choose, in the handler for where the connection is terminated, to terminate the thread yourself, it will not terminate. There is no reason for the operating system to couple the existence of the connection with the the existence of the thread. In the handler for the disconnect event, do a PostQuitMessage
 
2. In what thread context is the AssertValid issued? In what context is the socket created? How is it passed to the thread (see my essay here on CodeProject on UI threads). If you create the socket via an Accept statement in the main thread, you must Detach it from the socket object in the main thread and Attach it to the socket object in the worker thread, or the socket cannot work. My essay discusses how to do this.
GeneralThreads and SocketssussOscarins6-Aug-03 14:16 
Hello, i'm working with an application that uses threads. The main application must create some threads when you click on a button. The class what implements threads, inherit from CWinThread, and in the InitInstance method it constructs a socket connection to server. The connection is ok, but when the server needs answer the thread, it can´t (the thread doesn´t receive message). I think that the problem could be because threads can´t communicate with other remote applications, but i don't understand why the conection is correct with the server if it can't respond to the thread.
 
Speech for Visual C++
OpenGL in Visual C++
GeneralRe: Threads and SocketsmemberJoseph M. Newcomer14-Aug-03 6:28 
You must create UI threads. Sockets require UI threads. So you must use the form of AfxBeginThread that uses a RUNTIME_CLASS parameter.
Generalneed window handle in the UI threadmemberhillxy22-Oct-02 19:44 
I am writing a background thread which runs voice recognition. But IBM VR need a
window handle to start thr engine. Also the HWND are required for the engine to send message back to the main application.
 
So I need the new thread to create a hidden window which will dispatch engine messages
and the new thread to post recognized messages to the main window.
It is not hard to use createWindow ( instead of dlg.DOModel() which will show the
dialog ) somewhere in the threadm but how to manage the message loop of this created
new hidden window.
 
Thanks
Hillxy
 

GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer22-Oct-02 23:34 
You are in a UI thread. The handler is free: you use a message map entry. For example, if the speech engine sends a message IBM_SOMETHING_HERE you would add
 
ON_MESSAGE(IBM_SOMETHING_HERE, OnIBMSomething)
or
ON_REGISTERED_MESSAGE(IBM_SOMETHING_HEAR, OnIBMSomething)
 
and your handler would be
 
LRESULT CMyThread::OnIBMSomething(WPARAM wParam, LPARAM lParam)
{
...whatever you want here
return ...appropriate value here
}
 
If you want to take that as an opportunity to PostMessage to the main GUI loop, that's fine.
GeneralRe: need window handle in the UI threadmemberhillxy23-Oct-02 4:02 
hi, Thanks for you prompt response first!
 
I understand what you mean. I am still not so sure
whether the IBM engine could send correctly to
the message queue of this thread.
 
When start the engine, a HWND parameter is
required by the engine API, therefore
the engine could send message to this HWND.
I assume there is no HWND, or sth could be
casted as HWND without create a new window
in the new thread, am i right?
 
If So, Create a sub window with thread or
a thread with window, which is more stable?
 
I have more coming up questions
 
Thanks,
Hillxy

GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer25-Oct-02 7:14 
Create an invisible window in the UI thread and pass its handle to the IBM engine. Typically you would create this in the InitInstance of the thread.
 
I have no idea what you mean by "create a sub window with thread or a thread with window". The language of the query makes no sense.
GeneralRe: need window handle in the UI threadmemberhillxy25-Oct-02 16:48 
Thanks,
 
You gave me the answer ,although my question is not so clear.
I meant " Create a Window within a Thread or Create a thread within a window"
 
By the way where can I find any sample on how to create an invisible Window
and handle its WM_COMMAND message(the Engine will send WM_COMMAND to the window)?
 
Hillxy
GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer25-Oct-02 17:43 
There is no concept of "creating a thread within a window". Threads own windows; windows don't own threads.
 
In the case of a UI thread, there is no magic. Create a subclass of generic CWnd in the InitInstance of the thread. If the engine is sending WM_COMMAND messages you must have a spec on them (this is actually an mind-bogglingly poor design; a good design would send a Registered Window Message to a window! But you did say it was from IBM...). Write an OnCommand handler. Or tell me what the spec is and I might be able to suggest a better approach, e.g., ON_CONTROL
GeneralRe: need window handle in the UI threadmemberkokie29-Oct-02 7:27 
Hey Joseph.
Would you have any idea why something like this:


OnChar(...)
{
PostThreadMessage(id,msg,0,0);
}

 
would cause a deadlock?. When ever i type too fast a deadlock in the primary thread occurs and freezes the entire app.
 
Thanks.
GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer2-Nov-02 10:29 
I presume that the OnChar is occurring in a thread. How is this getting to the thread? A UI thread normally would not be able to receive an OnChar because it normally wouldn't have a visible user window. If it does, and it is a child window, what is the parent of the child?
 
If the parent of the child window belongs to any other thread than the thread which holds the window which is receiving the characters, deadlock wouldn't surprise me in the slightest.

GeneralRe: need window handle in the UI threadmemberkokie4-Nov-02 13:51 
The OnChar is in my app's main view.It's in the form of CMyAppView::OnChar(...). I am doing a PostThreadMessage from the OnChar handler to a parser thread. I don't know how this process could have caused a deadlock in the app's main thread. Depending on how fast i press the keys the deadlock can be prevented,but it should not work that way. when i do a Sleep(130) after the call to PostThreadMessage a deadlock doesn't occur. I wonder if it may have anything to do with the app's message loop. I have not being able to make any progress in the last 2 weeks. Very discuraging.I haven't done any kind of synchronization that could cause a deadlock.
 
Thanks.
GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer4-Nov-02 14:12 
There is no way to get an OnChar directed to a UI thread if the control is in your main view. The concept has no meaning. The main GUI thread owns the window and there is no way to have any other thread receive the message. Of course, you could resend the message yourself, but in that case you are much better off creating a user-defined message to handle the problem.
 
An absolutely sure way to tell you are in trouble is if you have to put a Sleep() call in a thread to make it work. This always, without exception, indicates the design is flawed beyond hope of recovery. The fact that the deadlock is related to how fast you type indicates that the design is deeply flawed.
 
You are ignoring the implicit synchronization that always happens within Windows. Just because you are not explicitly doing synchronization does not mean synchronization is not occurring.
 
What are you trying to accomplish? You've been asking a very specific question without indicating the nature of the problem you are trying to solve. There is surely a good solution, but without knowing what you are trying to really do, I can't suggest the correct solution.
GeneralRe: need window handle in the UI threadmemberkokie12-Nov-02 13:52 
Here i come again. I have narrowed down my bug to the new operator,which results in a call to the c-run time routine "calloc".I suspect that suspending a child thread while it is in a crt routine,would result in a deadlock if the parent thread tries to execute in the same routine. I am not too sure of my suspicion. If you have any idea why a crt routine would cause a deadlock,hit me back.My next move would have to be giving you my entire code, and hope you don't get a copy,which i seriously doubtSmile | :) . It's a java IDE am developing, it's almost ready for beta once i solve this terrible dalema.
 
Thanks.
GeneralRe: need window handle in the UI threadmemberJoseph M. Newcomer16-Nov-02 12:52 
Define "suspending a thread" in the context you mean. You are right, that suspending a thread in the C runtime is usually a fatal error, but that is because you can always assume that suspending a thread is a fatal error. While it is possible for a thread to suspend itself safely, it should be treated as a fundamental programming defect to ever allow one thread to suspend or terminate another. Nothing will solve this but rewriting the code to do the job right.
 
However, calling calloc will not cause a thread to suspend spontaneously.
 
A thread, if you want it to "suspend", should block on an Event object. It should do this only when it knows it has nothing locked that could cause deadlock.
GeneralThreadssussbandy200023-Sep-02 5:28 
HI! Im looking for very basic information about threads, how to use it in programs. I found your article, but i think its a bit too high for me. Do you know any locations where i can gat a good and quick introduction?

GeneralRe: ThreadsmemberJoseph M. Newcomer23-Sep-02 15:27 
I'm not sure about tutorials. Have you tried here on codeproject? Or post the question to the newsgroup microsoft.public.vc.mfc.

Generalproblem: ui thread, csocket classsussexxi17-Sep-02 13:25 
hi there ...
 
following situation:
i've derived a class named myThread from CWinThread, now i want to create a CSocket object:
 
myThread.h
...
protected
CSocket m_Socket;
...
 

myThread.cpp:
 
myThread::CPopThread()
{
m_Socket.Create();
// something else ..
}
 
the problem is, if i try to run the thread "AfxBeginThread(RUNTIME_CLASS(myThread));" - a Debug Assertion failed in socketcore.cpp, line 338.
 
the line:
BOOL CAsyncSocket::AsyncSelect(long lEvent)
{
...
-> ASSERT(pState->m_hSocketWindow != NULL);
...
 
does anyone knows why?
is it a problem with the message loop?
please help.
 
greetz exxi
 
ps: sorry for my bad english
GeneralRe: problem: ui thread, csocket classmemberJoseph M. Newcomer17-Sep-02 17:02 
You did not say whether the error occurred during the thread launch or after the thread had started, nor have you indicated the traceback, or what the thread might have been doing. Therefore, it is hard to guess what might be wrong. You need to tell useful information, for example, what was the value of pState->m_hSocketWindow? While we know it was not NULL, this is not terribly interesting; knowing the specific value is important. I've not seen anything like this happen in any of my threads, but then I tend to get the socket in response to an Accept, then hand it across, so I've not done anything that might result in this sort of error.
 
Questions:
(a) what is the value of the variable which is not NULL?
(b) has the thread performed any execution at all? (that is, did the .Create already get executed, or is it being executed, or what?)
(c) Who calls CPopThread, when, and why? (This supplements (b))

GeneralRe: problem: ui thread, csocket classsussexxi18-Sep-02 1:59 
ok .. sorry
 
(a) the value of m_hSocketWindow is (was) NULL
(b) .Create was already executed, i've done a step by step execution and it guides me throug some of the mfc sourcecode. quite before the error occured the program stays in the message pump while-loop of cwinthread::run()
(c) cpopthread was called by a cwnd object which is my m_pMainWnd of the main thread
 
so far so good...
 
i've tried something:
 
(1)
...
CPopThread::CPopThread()
{
m_Socket.Create();
}
 
CPopThread::CPopThread(CWnd *pWnd)
{
CPopThread();
}
 
BOOL CPopThread::InitInstance()
{
m_Socket.Connect("pop.lycos.de", 110);
return CWinThread::InitInstance();
}
...
 
i've created my own overloaded public constructor with some dummy parameters which calls the standard constructor of cpopthread, then i've ran the thread the 2-step way you suggested.
-> m_Socket.Create() works now (returns TRUE)
 
(2)
...
CPopThread::CPopThread()
{
}
 
CPopThread::CPopThread(CWnd *pWnd)
{
CPopThread();
}
 
BOOL CPopThread::InitInstance()
{
m_Socket.Create();
m_Socket.Connect("pop.lycos.de", 110);
return CWinThread::InitInstance();
}
...
 
same starting procedure, but this won't work
it results in a "unhandled error, read exception", the error occured in line 178 of map_pp.cpp:
 
void* CMapPtrToPtr::GetValueAt(void* key) const
// find value (or return NULL -- NULL values not different as a result)
{
->>>>> if (m_pHashTable == NULL) <<<<<-
return NULL;
 
UINT nHash = HashKey(key) % m_nHashTableSize;
 
// see if it exists
CAssoc* pAssoc;
for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
{
if (pAssoc->key == key)
return pAssoc->value;
}
return NULL;
}
 
i can't read the value of m_pHashTable ...
 
....
 
it's confusing me a lot. what is wrong? some idea?
 
thanks in advance for your effort. exxi

GeneralRe: problem: ui thread, csocket classmemberJoseph M. Newcomer18-Sep-02 7:14 
Well, you pretty much answered the question. You say that CPopThread was called from the main window. This is what is wrong. You called it from a different thread, so the socket is owned by the thread that calls it. It must be called by the thread that uses it, or you must use CSocket::Attach to attach the socket from within the thread, having detached it from the original thread.
GeneralRe: problem: ui thread, csocket classsussexxi18-Sep-02 20:18 
ok this sounds clear. But i thought, if i define the member variable m_Socket in the coresponding header file, call .Create() in the constructor or InitInstance() of the thread, then the socket is owned by the thread. I do not handover a socket to the cpopthread wich was previously created in the main thread.
 
Anyway your answer gave me the important hint:
to solve the problem, i've to call the AfxSocketInit() within the InitInstance() of my CPopThread - after that the socket works fine.
previously i did the call of AfxSocketInit() in the InitInstance() of the main thread (CWinApp). the AfxSocketInit() is a per process initialisation of the windows sockets - an that was the problem.Roll eyes | :rolleyes:
 
thanx. exxi.
 

GeneralRe: problem: ui thread, csocket classmemberJoseph M. Newcomer19-Sep-02 4:38 
Well, you said you created the socket in the context of the main frame. It doesn't matter what class the constructor is in, or the .Create operation; what matters is that the creation take place in the context of the thread itself (a class is not a thread, even if it is a CWinThread). Also, it is critical to test every return value, and if there is a failure make note of the error code; otherwise, you are trusting blindly that something works. For example, if you had tested the return code from .Create you would have discovered immediately what the error was. Creating the socket in the constructor was a mistake. (If you do something like this, you must be prepared to throw an exception: that's one of the main reasons we need exceptions, because constructors cannot return values!) In addition, by putting the socket creation in the constructor, this can work only if the CPopThread object is instantiated in the context of the thread (not the main GUI thread). Do not ever confuse a class or class instance with a thread context; they are only vaguely related.
 
The documentation is erroneous in that it does not state that AfxSocketInit must be called in each thread.
GeneralProblemsussmallio24-Jul-02 9:21 
I am trying to write a chat program for the fun of it.
This requires me to be able to receive and send at the same time.
I have the sending and recieving down, but in order to send, it has to receive something, so i need to use threads so the recieving end works in the background. However, I cannot figure out how to do this. How can i get the recieving thread to update my reciving window? I have been trying to figure this out for days now...

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 17 May 2000
Article Copyright 2000 by Joseph M. Newcomer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid