Link to home
Start Free TrialLog in
Avatar of kavint
kavint

asked on

COM Port and WM_TIMER

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

In order to get the WM_TIMER message you must be executing a message loop.  Are you?  It is not interrupt driven.  
Avatar of kavint

ASKER

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?
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?
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.
Avatar of kavint

ASKER

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



Avatar of kavint

ASKER

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? '

ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

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
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.
Todd, can you elaborate on the "appear to be posted" part?
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.
Thanx.

Avatar of kavint

ASKER

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.
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?  
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.).
Avatar of kavint

ASKER

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?

Avatar of kavint

ASKER

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.

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?
Avatar of kavint

ASKER

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?

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.