MFC application freezing while updating CListCtrl - c++

I have a CListCtrl in my MFC application. The list needs to be updated when I get some notification from the server. Updating list works quite good when there are less notification as operations on the list are less. But in case of heavy load, list control and in turn the application gets freeze.
I am aware of updating UI items in the separate thread in case of bulk updates, but in this case I have the notifications that can come in any order and in any volume, I need to handle in such way that my main thread is not getting blocked.
If anyone faced the issue before please suggest the approach for this case.

You could put all the updates into a queue. Then do a limited number of updates from the queue to the control in the OnIdle function. OnIdle is called when your GUI message queue is empty. It could do up to, say, 20 updates and then return. The main thread would than process any GUI input and when finished with that it would call OnIdle again. In this way you delay and spread out the updates while keeping the GUI alive.

I had a similar situation and resolved it using a Timer. Only when the Timer ticked the ListCtrl could got updated.
Side note: You should do
SetRedraw(FALSE);
before a bulk update
and
SetRedraw(TRUE);
after.
You should not have the control drawing itself at a one-by-one item level, when doing a bulk operation.

Use Thread.I had the same problem and I solved it by just having the loop of adding elements into the clistctrl in thread function. That is,is the POSTMESSAGE() function in the thread should be called as much time as we want to add elements .
MFC Application getting stuck when adding list control elements
Also refer the above link to get some idea

Related

Search/Filtering functionality blocks the Main(GUI) thread

I have a custom table and I have implemented a search/filtering function which goes through all the elements in the table and then hides/shows the item in the table depending upon whether that item/element matches the one we are searching for.
For example, let's say I have a text control and I type "wxwidgets" in it then my custom function will go through all the elements in the table and hide the elements that do not match this "wxwidgets" entry. This works fine and I am correctly able to hide/show the elements. But the problem is that this search blocks the main thread(gui) since I am doing this in the main thread. The table has around 1000 entries or can be more in the future. My question is how can I avoid this blocking of the main thread. I am thinking of using another worker thread that will do this searching of elements. But then I read that "no secondary threads should call gui functions". But then how can i show/hide the elements of the table from the worker thread. For example, currently in the main thread I use Show(true) or Show(false) to show/hide a particular entry from the table and all this is done while I am in a for/while loop. But if i implement this(the for loop) in a worker thread then according to the quoted advice i should not use the Show() functions from inside that worker thread. What can be done in this situation? Also, is there any other way/advice of doing this searching for elements of the table. I am thinking of starting a new detachable thread every time the user enters some text in the text field. And then delete that old thread if the user appends some more text to the text field and start a new thread which starts searching from the beginning. Is this the right solution for this?
The problem is that inside my for loop i am using the wxWidgets functions. For example, this is what my for loop looks like:
void AnotherClass::onTextChanged(wxCommandEvent &event)
{
for(int i = 5; i<154;++i)
{
SomeClass *element = dynamic_cast<SomeClass*>(FindWindowById(i));
if(element.GetLabel() == textEnteredInTextCtrl)
{
element.Show(true);//element found
//update the necessary layout here using layout call
}
else
{
element.Show(false);//element not found
//update the necessary layout here using Layout() call
}
}
}
This is the main part of the search. Now inside the workerthread should/can i use the functions like FindWindowById() and GetLabel()? Are they considered GUI functions or not so that I can use them from the worker thread? Can i or can i not use FindWindowByID() and GetLabel() and other similar functions(like Layout() and Show()) from inside the worker thread. How should I make this work? I mean I know how to use wxThread and send events using QueueEvent and already have another worker thread in my program that does some other calculation but I am asking about how I should make it work in this particular case.
Another solution suggested by QuentinC would be to use a timer. His suggestion is as follows:
In my case, I don't start refreshing the list immediately after the
user has typed a letter in the search box. Instead, when the user has
typed a letter (wxEVT_TEXT), I start or restart a timer of 500ms. Only
when the timer goes out (the user stops typing for 500ms) then the list
is refreshed. Again, this is a measure to avoid a rapid succession of
useless refreshes.
But in this case of using a timer i have several queries. I am sending the wxEVT_TEXT from CustomTextCtrl's onTextChanged method to this class' onTextChanged method. I guess i could start the timer of 500ms inside the onTextChanged method of the CustomTextCtrl class when the user types a letter. But then where should i check that the timer is still running? In the CustomTextCtrl's onTextChanged method or inside the AnotherClass's onTextChanged method?
So for clarification i have two classes:
the CustomTextCtrl class which have a onTextChanged method which uses event.Skip() to forward this event to its parent.
The parent class AnotherClass which also have a onTextChanged method and this method receives this forwarded event and do the searching and updates the table.
Where and how should i start/restart/stop the timer to update the UI?
NOTE: The process of filtering the elements is working perfectly but the only problem is that the main(GUI) thread is blocked when the user type some text inside the textctrl. After lets say 6 or 7 seconds, the text appears inside the textctrl and the UI is updated. I don't want this unresponsiveness of the main UI for 6-7 seconds.
Also, note that i am not using any wxList/wxGrid. I am just using wxPanels and wxStaticText and using show/hide on them.
Edit: One improvement in the code above is that to only use Layout() call from outside the for loop. If i use the Layout() calls from outside the for loop then the search functionality works almost instantly. But this(method) still has the potential of blocking the main thread in the future if the table has many more elements. So i want to use a thread or a timer method. But i don't know how the secondary thread could use the gui functions or how can/should i use a wxTimer method(if any) to solve this problem.
I have several thoughts on this subjet
A) If you have a speed issue, then you better profile your code, to see where the bottle neck is.
B) Calling GDI functions from a not-main thread is risky. Maybe just asking for window-id and its label is not that dangerous, but I think calling Show() definitely is.
C) This piece of code is mainly GUI related. I don't think a worker thread is useful here. But stacking similar callings may improve its speed. For this, I have three advises:
Use CallAfter() passing the elemnt.Show() method
Use Freeze() before the loop and Thaw after it.
Call Layout()only once, right after the loop. About this I wonder if Show()/Hide() controls is better than Enable()/Disabñe()
D) Because you call FindWindowById() so many times, and also many user changes, it will be better to cache all affected windows in a container (a std::map with id as the key). Then, inside the loop use the container instead of 'FindWindowById()`.
E) As a last resource, if the GUI is still blocked, use wxYield() every xxx (say 100) loop-iterations. Depending of pending messages this solution may get things worse (reentrances, crossed effects, etc).

How to make a thread in MFC for moving slider control with respect to audio file that is being played?

I was able to move SliderControl according to the position using CSliderCtrl::GetPos , being played by the program. (This is a part of my Music Player MFC project).
But I need to do this automatically without any notification/events ....
I thought of creating a thread that will move slider after clicking on play button.
You generally want to have exactly one thread updating the UI (and doing as little else as possible).
It would almost certainly work better to have a secondary thread playing the music. It can send a message to the UI thread, and the UI thread updates the slider control position when it receives that message.
It is always good to update the UI from the main thread instead of adding a new thread for updating UI. Better you can perform your background tasks by using a worker thread and update the UI by sending a message to the main thread when ever required.
In your case, you can have a worker thread to play the music and send a message to the main thread to update the slider position.
::SendMessage( AfxGetMainWnd()->m_hWnd, Message_Id, ( WPARAM )&String, 0 );
You can use the APIs CSliderCtrl::SetPos() to update the position.

Updating Windows Form - Visual C++

Hi I am currently writing a windows form application using visual studio 2010, the application I am writing needs to update labels on the form independent of any events happening - I know it is possible to update the form using event handlers but this requires and event to happen to do something.
I am planning to to use some form of main loop to update the form constantly - I just do not know where to place such a loop? I think I've heard of something called the message loop, would it go there? Or would I have to create a separate thread to do so - and if I did create a separate thread , would I have problems accessing controls created in another thread?
Basically I am modelling an elevator system and need to update certain details about the elevator to the form constantly without any buttons being pressed , e.g current floor, going up down ect
I can post code if need be
You almost certainly want to do the background work in a worker thread. Have that worker thread send updated data to the main thread in a way that triggers an event. The main thread then updates the UI based on the updated data in reaction to the event you triggered.

how to change GUI while processing

I am new to Qt Programming, but I have basic on C++.
I want to update my GUI while it is processing, example:
while (....)
{
do some calculation...
if (condition fulfill)
change the color of label.
}
However, I realise that I failed to get the result I want (update the GUI while processing). The GUI will only update after the while loop.
Why is it so? Anyone can help?
In addition, I wish to "slower" the color change since the processing is too fast and I can't see the animation. Any idea to do it?
Thank you very much!
Clarification:
Actually I wish to update the GUI while I am processing...Meaning that, if I have 100 iteration, after each iteration I wish to update the GUI immediately.
Use a QTimer. This will allow you to control the speed of your animation and keep your UI responsive.
You have to place your processing code to another thread and update the gui, because like this GUI will be waiting for your process to end and will refresh after its end
read more here:
http://www.qtcentre.org/threads/41545-How-to-refresh-GUI-while-heavy-processing-is-ongoing
http://www.qtcentre.org/threads/32416-Update-GUI-from-another-thread
Forcing the Qt GUI to update
You don't necessarily need a thread.
Calling QApplication::processEvents() will process pending events, including any redraws you may have caused during your processing.
If you wish to animate the color to indicate that the system is currently working, you might want to use QApplication::setOverrideCursor to show a waitCursor, or a QProgressDialog instead.

Event handler in Qt with multithread

Does any one know how the event handler manages the posted events?
In my app i have two threads (guiThread and computationThread). After an exception is thrown I call postEvent(..) to an existing dialog. The Qt-Event-Handler holds this one back until the dialog is closed.
Sorry my question is a bit cloudy. I will write it more exactly, if I have time left. I found a work around. But for me the problem is still interesting.
As mentionned in the Qt documentation about QCoreApplication::postEvent :
When control returns to the main event loop, all events that are stored in the queue will be sent using the notify() function.
...which explains why the Qt Event Handler holds the event until the dialog is closed.
If I understand correctly what you want to do, I would try using sendEvent.
I'm guessing that the dialog you created is modal, which would mean that it is running its own event loop. No events posted to the general guiThread will be processed until all modal event loops are exited.
Alternately, if you need the dialog to both be modal and know about the event, you could post the event directly to the dialog. You'll need to figure out how to handle pointers in a shared manner, but if nothing complicated is going on, you might be able to use the QApplication::activeWindow() function.
As others already wrote, I believe this behavior is caused by the fact that the dialog starts its own event loop.
If you use Qt4, you can try using queued signal/slot connections as an alternative to posting events.