2
votes

I am rewriting a MFC application that has a lot of problems. The main problem is it is unstable.

It is a GUI application that communicates with an external module via USB. So it runs a communication stack every n milliseconds by using a timer. However system calls are not allowed inside timer callbacks so the program is unstable and crashes and hangs a lot because of this.

So I have to rewrite the application to run the communication stack in a background thread. Another problem here is that the data is not completely separated from the presentation and if I use another thread I have to make sure I protect shared resources.

So, mainly, the communication stack will notify the application that there is new data. This should be handled by the worker thread. It runs the communication stack, processes new messages and then locks the data struct while updating it and then it answers back to the module. It then sends a message with PostMessage to the Main thread to update the GUI.

But the user can also tell the application to send data to the external module. This can be done in 3 ways: 1. Send data once. The MAIN thread would then send a message to the worker thread to take a message out of a queue and send it to the module. 2. Send data periodically. This would need to use a timer inside the worker thread or a flag might be enough and it would send data every loop in the thread update function. 3. Send a message to the module and wait for a response. This would require to use a timer to check for timeouts inside the worker thread. On reception of the message the worker thread has to notify the MAIN thread so it can update the GUI with the response.

So I'd need to: 1. Run the communication stack in a separate thread. The comm stack is a state machine and calling it runs through it once checking for new data. There is no while-loop in it. You can also call a function in its API to send data.

  1. Send messages to the MAIN thread to update the GUI when things happen.

  2. Send messages to the worker thread to tell it to send data from the application.

So my questions are: 1. MFC uses Document/View model. I have a hard time figuring out the best way to match this with what I want to do or if I want to partly abandon that (skip the document and have my own way of storing the data). * How do I best organize my data? Have one big struct that contains all application data and then both the worker and main thread have to lock it when accessing it? * When I send a message to the MAIN thread to update the GUI how do I best map the messages to the functions? Using the MESSAGE_MAP? But the message maps are for the windows not the threads? I need to be certain only the MAIN thread accesd the GUI. I'd need to map each different change in the GUI to a certain function. That's a lot of messages because there is not one uniform display in the GUI but a lot of different tabs (message log, objects, custom messages).

  1. How does messages get processed? Since the worker thread can access the stack both by running it normally and when the application tells it to send a message I have to finish one call to the stack before a different one is made. If the thread update always finishes what it does before it processes new messages, this is not a problem. Or could I potentially be inside the stack when the timer hits or I get a new message from the MAIN thread and it starts processing the stack as well? Maybe I have to lock the stack not only for other threads but to make the sure the worker thread itself does not access it in 2 ways "at the same time".
1
Couldn't fit whole emssage into post so please read these comments too.2. How does messages get processed? Since the worker thread can access the stack both by running it normally and when the application tells it to send a message I have to finish one call to the stack before a different one is made. If the thread update always finishes what it does before it processes new messages, this is not a problem. Or could I potentially be inside the stack when the timer hits or I get a new message from the MAIN thread and it starts processing the stack as well?user1190832
Maybe I have to lock the stack not only for other threads but to make the sure the worker thread itself does not access it in 2 ways "at the same time".user1190832
"system calls are not allowed inside timer callbacks" - who told you that?Mark Ransom
Well, I cannot find the resource now but I read it somewhere and found the source believable. Not sure if it was some official docs or stackoverflow. Also a person that has a lot of knowledge about Windows programming said it. Is it not true? There were several problems with using a timer. One problem was that the timeKillEvent was called when the callback was executing. Another place in the code uses the timer differently. Maybe I should not use void CALLBACK TimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 ) but rather just OnTimer?user1190832
A timer callback is simply a convenience provided by Windows that gets called during normal message processing in place of the usual WM_TIMER handler. It doesn't have any restrictions that don't apply to any other message handler. The documentation for SetTimer and TimerProc do not mention any restrictions.Mark Ransom

1 Answers

2
votes

Re messages and message mapping:

The windows message queue does not interrupt your program or thread. Messages wait in the queue until you return to the message loop, then it dequeues and dispatches the next message, if any is waiting.

You are correct that the message map (in the main thread) is for windows. Your worker thread must post or send messages to a main thread window. If you have a lot of such messages it is probably best to post them all to the main window (CMainFrame). Put ON_MESSAGE items in the CMainFrame map for each message. Then the handler functions in CMainFrame can call other windows as appropriate to update GUI displays.