Solved

COM Port and WM_TIMER

Posted on 1998-04-28
19
377 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
  • 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
 
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
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Healthcare organizations in the United States must adhere to the guidance of both the HIPAA (Health Insurance Portability and Accountability Act) and HITECH (Health Information Technology for Economic and Clinical Health Act) for securing and protec…
In this article, you will read about the trends across the human resources departments for the upcoming year. Some of them include improving employee experience, adopting new technologies, using HR software to its full extent, and integrating artifi…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

757 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now