UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected)
-
taking what @jsulm said to heart, I would suggest the following.
store all your (after processing) data in a struct and check if any data was actually updated with new values and only then try to emit signals to the ui-thread.
For emitting the signal to the UI. I would suggest a QTimer and a QTime object. You save the time you last updated the UI, if the time is < than 16 ms (roughly 60hz rate) shedule an update for the next Frame via QTimer if more time passed, send the signal directly.
You can pass structs in a signal (across threads), if you register it with the Meta-object System
-
for each connected PLC@client a new thread is created
Only a maximum of 2 client will connect to it.
Why would you multithread with only 2 clients? you are probably losing efficiency there. See this example
-
@jsulm said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
@VikramSamy You could reduce the load on UI side by not updating each 0.02sec as this is higher than what a typicsl display can show.
ok i just changed the PLC@client update rate to 0.2s rather than 0.02s as before...quick testing shows that the responsiveness way much better and nice, but previously when i used 0.02s it also good and nice but eventually becomed sluggish...anyway il continue to test and tune the client@PLC update rate and check the resposiveness and will update here..
-
@VikramSamy said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
eventually becomed sluggish
sounds like there is some issue in your code. Maybe memory leaks?
-
@VRonin said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
for each connected PLC@client a new thread is created
Only a maximum of 2 client will connect to it.
Why would you multithread with only 2 clients? you are probably losing efficiency there. See this example
basically the code framework/architecture is already written previously, and im just modifying by adding other stuff to accommodate new requirements, as per that i dont want change the underlying concept used, anyway il look into example and study it.. if my UI & tcpserver implementations really bad concept, then definitely il need to revised it but as for my UI is just simple monitoring page with few button and a firebird database implementations (anyway database is not implemented yet), as for now if its works fine with current architecture then should be ok for me. So the main reason im using this architecture is because alot work have already been done previously and im adding new functionality as per new requirements only... maybe in future we might have more clients connected too....
-
@jsulm said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
@VikramSamy said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
eventually becomed sluggish
sounds like there is some issue in your code. Maybe memory leaks?
i need study & check about this memory leak too, stime at begining itself it start to sluggish, and stime after a while....
but as for now changing the client update rate to 0.2s seems working well...will start test more and update..
-
@J.Hilk said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
taking what @jsulm said to heart, I would suggest the following.
store all your (after processing) data in a struct and check if any data was actually updated with new values and only then try to emit signals to the ui-thread.
For emitting the signal to the UI. I would suggest a QTimer and a QTime object. You save the time you last updated the UI, if the time is < than 16 ms (roughly 60hz rate) shedule an update for the next Frame via QTimer if more time passed, send the signal directly.
You can pass structs in a signal (across threads), if you register it with the Meta-object System
currently the architecture works similar by passing the processing data in a struct through a signal(across threads) but the signal is immediately emitted once the processing done, there no schedule to update as your suggestion. anyway currently the client is updating every 0.01s (100ms) and as per that the UI have sufficient time refresh itself without getting lag/slow. so far it is working fine.
Anyway as the data received is to update UI which is 'bar-graph like indicators" which looks like a real time HI-FI graphic equalizer which rises up or down according to signal strength, as per that i just want to continue updating it although there is no status change received, as u suggest i try to update only when status change, but it cause the bar graph patterns getting stalled and not so nice,not going up & down nicely, so as per that i just continue updating no matter got changes or not ...anyway i got another idea as below:-
as i told before there is 2 PLC updating the server with the same set of data's, one is for redundancy purpose..as both will run in their own separate thread when both is connected and the respective threads emits a signal after completing the data parsing,then the UI update slot is called to refresh the UI to latest status.
The idea now is to use only 1 set of data from only 1 thread and not use the data returned from the other thread, because updating the UI constantly with same set of data's also another waste processor time and makes the UI lagging and slow.
So how to block a thread, and only let 1 thread to continuously processing while blocking the other thread,to achieve something as below :- e.g
thread A and thread B is created after both PLC1 and PLC2 is connected, but only the data returned from thread A is used to update the UI and thread B is blocked from running, thread B only can run if thread A is deleted when the PLC1@client is disconnected and VICE VERSA.
in other words when both client connected, only thread A data will be used and Thread B must be ignored, if PLC2@client is disconnected then use thread A data from the connected PLC1@client, and when PLC1@client is disconnected then use thread B data....something like this..
as im new to multi threading or thread based program and also QT, i just try to implement flag in the struct passed by the thread, which states if both client is connected and etc , and checking it before update the UI but it doesnt work...my questions is do we need to use something like mutex or any kind of locking mechanism or this can be achieve by simple flag based communication like in normal embedded c program without threads,
-
Hi,
How do you determine that your PLC are connected ?
-
@SGaist said in UI Resposiveness + Multithreaded TCP server-client (UI lags, slow, less responsiveness when 2 client connected):
Hi,
How do you determine that your PLC are connected ?
in the code , there 3 main class/part or i can say 3 object for the communication between the UI and the PLC.
-
DATA_PROCESS
which contains the functions to parse the data and a global
struct to hold received status, within the global struct there is
a ID variable to identify which PLC send the data.there is also
private variable called PLC1connect & PLC2connect to set or
reset PLC connections. -
TCP_SERVER- to handle TCP connections....
-
Connections THREADS
To receive and parse the data by calling the DATA_PROCESS.
Once a PLC is connected and a thread is created, the thread will call Data Process Object to parse the data, and after parsing, the ID of the PLC is loaded into the 'status struct', and PLC connection TRUE is set according to the ID received ,so we know which PLC is connected.
In the DATA_PROCESS code also, a QTimer is set to emit signal every 100ms and connected to a slot called "check_connections", in the check connections function just check if PLC1 connection is TRUE and if yes set to FALSE, and then next check PLC2 connections and if TRUE set it to FALSE and just repeat every time Qtimer emits.
so basically each time a thread is receiving the data from the PLC client, it will set the Connections to TRUE according to the PLC ID received, and at every 100ms, check_connections function will set it to FALSE, and in the check_connections functions, it is also checked that if it is maintain FALSE for more than the predetermined time, e.g when a PLC is disconnected, then PLC loss status is emitted to the UI thread and PLC communication indicator is off'ed.
this is how it is determined if the PLC are connected. The thread once received a complete packet with the PLC ID, then the PLC1connect or PLC2connect is set to TRUE and disconnection is check by the check_connections functions as above
So what im thinking here is, now got 2 threads calling the DATA_PROCESS object and updating the received data to the 'status struct' and then emitted to the UI by calling the UI update functions/slot. This calling of DATA_PROCESS is done in the "Connection_Thread::Ready_Read()".
So i guess i need lock one of thread,(or atleast stop it from emitting its update signal) when both PLC are connected, and only allowed 1 thread to do the processing and updating, and if the particular PLC is disconnected & its thread destroyed, then unlock the other thread to continue the processing,.. basically this to achieve redundancy when 1 PLC fails we still have the data of the other PLC to update the UI, anyway i need to do it in software because i have some hardware limitation/PLC programming limitation to support the PLC redundancy.
-
-
Rather than having both your PLCs competing to write in some global structure. You should rather have them independently fill each their own structure and have some sort off watchdog switching from one or the other if needed.
Depending on the how often the PLC are supposed to send data, you should maybe consider restarting the network check when you receive data rather than having that again competing with incoming data.