?
Solved

COM Port and WM_TIMER

Posted on 1998-04-28
19
Medium Priority
?
385 Views
Last Modified: 2013-11-25
I have an application that needs to Test the functioning of a test equipment thru a COM port.My requirement is that when the test begins(that is when the port is opened up), I need to display a Dialog that has a Progress bar control to indicate that my test is in progress.

What I have done is, when the test begins, I create a New Modeless Dialog and within the dialog.cpp I have implemented the OnTimer function. The function sets the position of the Progress Bar with a rand() function.

The problem is, when I open up the port, Windows doesnt seem to send WM_TIMER messages at all and my progress bar stands still till the port is closed.
Theoretically, windows should resume multitasking after it opens up the port.
Any help would be much appreciated.
0
Comment
Question by:kavint
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 7
  • 2
19 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1166369
In order to get the WM_TIMER message you must be executing a message loop.  Are you?  It is not interrupt driven.  
0
 
LVL 2

Author Comment

by:kavint
ID: 1166370
To get the WM_TIMER message, I have a SetTimer() function in the OnInitDialog() of my Dialog implementation file. That should take care of sending the WM_TIMER messages, right?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166371
WM_TIMER messages require that a message loop be executing.  For a modal dialog, windows will run its own message loop, so you don't need to.  (But you can't be doing something else in the thread at the same time).  For a modeless dialog (which is what you said you had) you must be executing a message loop to get the timer messages.

What code is executing while you are "waiting" for the time messages?
0
Three Reasons Why Backup is Strategic

Backup is strategic to your business because your data is strategic to your business. Without backup, your business will fail. This white paper explains why it is vital for you to design and immediately execute a backup strategy to protect 100 percent of your data.

 
LVL 22

Expert Comment

by:nietod
ID: 1166372
If you have code that does something like

1. Open port.
2.  Execute some testing loop for a while
3.  Close port.
4.  Return to message loop.

You will not be getting timer messages.  
If this is the case, there are ways around this.  For example, multiple threads, or continuing the message process durring your test.  We can discuss these options, if this is the case.
0
 
LVL 2

Author Comment

by:kavint
ID: 1166373
You are right. After I open the port, there are several operations taking place that need the communication with the port.. As I am not involved with those hardware electronics part, I cannot possibly elaborate on that. But you have got the point right.
Once the port is closed, then I resume my tasks with the application and I do not have a message loop.

I read this info. from a technical article which says that WM_TIMER and WM_PAINT messages are low-priority and if the windows finds some other high-priority messages in another queue, it would execute those.
and I found this one too

'Timer callback functions are invoked through a posted WM_TIMER message. The WM_TIMER message has NULL as the hwnd member and the lParam points to the callback function. The callback function is invoked by Windows when a WM_TIMER message with a NULL hwnd is passed to DispatchMessage.
Remember that CWinApp is derived from CWinThread, and if your timer is established in the primary thread then your application will need to override PreTranslateMessage in its CWinApp-derived class'

Will it help if I check for WM_TIMER in my dialog class by overriding PreTranslateMessage or is it imperative to have a message map?
Please elaborate.
Thanks



0
 
LVL 2

Author Comment

by:kavint
ID: 1166374
The last line of my previous comment should read

'Will it help if I check for WM_TIMER in my dialog class by overriding PreTranslateMessage or is it imperative to have a message loop? '

0
 
LVL 22

Accepted Solution

by:
nietod earned 100 total points
ID: 1166375
First off.  I'll back up a little.  There are two ways your window procedure gets messages.  Sent messages (SendMessage()) go directly to the window procedure.  That is, some code somewhere calls the window procedure.  This can be done at any time (more or less).  Posted messages are placed in your message queue (or at least seem to be, sometimes they aren't really there)  These messages make it to your window procedure only when you are in a message loop.  Timer messages (and paint messages) are posted, not sent, (actually they APPEAR to be posted, niether really are posted) so they are not obtained unless there is a message loop running.  Yes, they are lower priority so they will not be received when there are higher prioroty things in the queuq.  However, they won't be received at all if there is no message loop.  Is that part clear?

continues.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166376
There are three main ways out of this.

First, you can create a new thread and do the "port testing" in the new thread and let the original thread display the dialog and return to the message loop.  

Second, if the port testing code involves some sort of loop (or loops) that do the testing.  You can put message processing code in the port testng code.

Finally, the reverse of the previous.  If there are a bunch of steps to the port testing, expecially if the steps tend to involve waiting for the port to respond. break up the port testing code and call it from the message loop.  You will probably use a timer to indicate when you should try the next step of the testing.

If you explain more about your code, I may be able to help you choose a design.  The 2nd thread option will probably have the least impact on what you have already written.
0
 
LVL 11

Expert Comment

by:alexo
ID: 1166377
Todd, can you elaborate on the "appear to be posted" part?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166378
Paint messages aren't actually placed in the application's queue.  When GetMessage()/PeekMessage() find that the queue is empty, they then look for invalid window regions, if found they return a WM_PAINT message.  That is why Paint messages have lower "priority".  Its not a priroity queue.  Its FIFO all at the same priority, but paint messages don't get produced unless the queue is empty so they are affectively low priority.

I believe Timer messages are the same.  They are not placed in the queue, but are instead checked for when the queue is empty.  

Keyboard and mouse event are also not placed, in the queue, at least not right away.  They go into a system queue that is shared by the application.  (They might go to the application queue eventually)  The reason for this is that it isn't always possible to tell which application should receive the event.  if you get a mouse click followed by keyboard press, the mouse click might cause the focus to change and it might change to a new application.  Thus the keyboard press might need to go to a different application.
0
 
LVL 11

Expert Comment

by:alexo
ID: 1166379
Thanx.

0
 
LVL 2

Author Comment

by:kavint
ID: 1166380
Thanks Nietod! The second thread option seems to be the possibel solution because I dont feel safe to meddle with the code written for the port testing.

I did try creating a thread class with my Dialog display code in the InitInstance, but it doesnt seem to work.
I initialized the thread by calling AfxBeginThread(Runtime class of the thread object).While debugging, I found that the execution reaches InitInstance but fails to bring up my Dialog.
Is there anything that I have missed out?
Thanks for your help.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166381
I'm not sure.  I don't use MFC.  

It seems like that you are trying to do is create a UI thread.  I that right?  You could create a worker thread an do the port test in the worker thread and the dialog in the regular thread.  If you are creating a UI thread, which is doing the dialog and which is doing the testing?  
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166382
Out of curiosity, and for my personal improvement, is there are reason you gave me so low a grade?  I quickly figured out what the problem was an proposed solutions which we are working on.  It seems to me like I was doing a good job.  (Although now we are entering an area (MFC threads) where I'm not so knowledgable.).
0
 
LVL 2

Author Comment

by:kavint
ID: 1166383
The UI thread will do the dialog and the primary thread will take care of the testing as of now. The reason I dont want to meddle with the port-tesing code is a) I havent written that  part of the code and b)there are more than 10 user-created classes that perform the port testing and I am not sure how should I go about placing a message loop and if ata ll I do, where will I put it?

0
 
LVL 2

Author Comment

by:kavint
ID: 1166384
Well, it was a mistake when I did it the first time. Now looking at it I would have given a much better grading.
I appreciate your getting into the right track in solving the problem.

0
 
LVL 22

Expert Comment

by:nietod
ID: 1166385
I believe that you don't need to write the message loop.  It should be part of the UI thread.  Although their might be some member procedure you need to call that does the message loop.  I'm not sure.  

One potential problem with having the dialog in the new thread, is the stuff you mentioned about the timer messages and pretranslate and all.  I don't understand it, but the gist is that there might be times when timer messages won't come through in a multi-threaded MFC app.  Unfortuantely I don't understand either the circumstances or the solution.  If the dialog is created in the main thread and the new thread is a worker thread, this should not be a problem however.  In addition this might be more efficient.  It should work either way however, it just seems easier this way.

If you want to continue with the current design (2nd UI thread with dialog) Can you tell if the code that creates the dialog is every called?
0
 
LVL 2

Author Comment

by:kavint
ID: 1166386
It seems easier to have the workser thread do the port stuff.
I could give you an idea about how the code is organized.

There is this function OnClickedSendCmd() which is called on hitting the Execute button and that trggers off the test. Within this handler are various input and output statements to the COM port. Before the test begins however, I have to bring up this dialog and as the test progresses, the progress bar needs to get updated. Thats is the big picture. All I need to make changes is in this piece of Handler.
can I put this handler as part of a worker thread and if so, how will it affect changes to my dialog creation?

Here's my code to create the dialog
      pResultDlg = new CResultDlg();
      pResultDlg->ShowWindow(SW_SHOW);
      pResultDlg->UpdateWindow();

After this, the port-testing code begins and the WM_TIMER stuff is all handled in the dialog.cpp.

Is there anything that you need to know?

0
 
LVL 22

Expert Comment

by:nietod
ID: 1166387
Is there anything I need to know? Other than how to program in MFC?  

Here's about the best I can do.  The idea should be in the main thread, when the execute command is run.

1.   create the new dialog.
2.   create a timer for notifying the dialog when it should update.
3.   create the worker thread.  The worker thread should start with a procedure that does the testing.  The procedure must notify the main thread/dialog of its progress.  This could be done with a global variable of some sort, since the dialog is just going to check periodically.   A mutext will be needed to protext the global data.  (But you don't have to put it in right away)
4.  return to message loop.


When the worker thread is done, the dialog should be taken down.  This can be done by having the timer notification code test to see if the worker thread is done and if so closing the dialog.  How do you test to see if the worker is done?  There might be an MFC way to do this.  Aniother way is to use a global variable as a semaphore.  Another way is to use WaitForMultipleObjects() to wait on the thread handle.  If the thread is done, the thread handle is considered signaled so the wait will abort.  Not you want to use 0 for the time out time, so that the procedure doesn't actually, wait but instead returns immediately if the thread has not ended.  There is probably an MFC counterpart to this function, but I'm not sure what it is.  

I hope this helps.  
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This month, Experts Exchange’s free Course of the Month is focused on CompTIA IT Fundamentals.
If you're a modern-day technology professional, you may be wondering if certifications are really necessary. They are. Here's why.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question