I am developing a C++ MFC-based application that takes positional data over IP, does some stuff, sends it back over IP, then outputs it to the list control. Every packet is collected, processed and sent out. After the send, I pass the output function to a separate thread so the app can proceed to loop back for the next packet. The app processes around 3-4 packets a second, on average.
The problem is that the List Control function calls are slowing everything down and creates lag that can be seen on the receiving computer (it uses a map to track the positional data). It’s noticeable, especially because I added a button that toggles output calls on/off. When output is on, the lag is up to 60 seconds behind. When output is off, there is no lag and the map entity snaps to its actual location.
I isolated the problem to the List Control function calls that create each line of data in the List View field. I tried deferring the rendering of the text on the list using .SetRedraw(FALSE)
/.SetRedraw(TRUE)
before and after the calls, respectfully, and I discovered that function calls .InsertItem()
& .SetItemText()
alone was enough to cause the slowdown, even without being drawn to the GUI. Passing these calls off to a different thread didn’t work, but a colleague supposed that was because those functions access/call to the original MFC GUI thread, which would affect all branches from that thread.
So, is there a way to eliminate the problem or do I need to manage the data differently? I read about utilizing a Virtual List being a possible solution, so if anyone has insight about that I would love to hear it.
void OutputSend(struct Packet_Data sendData, int packetCount, int port)
{
int dataSize = sendData.data_size - RM_DATA_OFFSET;
TCHAR outputPacketCount[20];
TCHAR outputIndexRM[20];
TCHAR outputDataSize[20];
TCHAR outputPlayer[4];
TCHAR outputIP[20];
TCHAR outputPort[10];
TCHAR outputProtocol[20];
TCHAR outputData[4000 + 1];
//************
//Process and conversions code here. This is a negligible part and was eliminated as a possible cause.
//************
swprintf(outputData, (dataSize * 2), L"%hs", charHex); //convert
_stprintf(outputPacketCount, _T("%d"), packetCount);
_stprintf(outputIndexRM, _T("%d"), sendData.indexRM);
_stprintf(outputDataSize, _T("%d"), dataSize);
_stprintf(outputPlayer, _T("%d"), sendData.playerNum);
_stprintf(outputPort, _T("%d"), port);
_stprintf(outputProtocol, L"%S", sendData.protocol);
outputData[dataSize * 2] = ''; //NULL end TCHAR array
if (m_checkbox_output.GetCheck())
{
m_list_platform.SetRedraw(FALSE);
m_list_platform.InsertItem(0, outputPacketCount);
m_list_platform.SetItemText(0, 1, outputIndexRM);
m_list_platform.SetItemText(0, 2, outputDataSize);
m_list_platform.SetItemText(0, 3, outputPlayer);
m_list_platform.SetItemText(0, 5, outputPort);
m_list_platform.SetItemText(0, 6, outputProtocol);
m_list_platform.SetItemText(0, 7, outputData);//data
for (int i = 0; i < m_list_platform.GetHeaderCtrl()->GetItemCount(); ++i)
m_list_platform.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
m_list_platform.SetRedraw(TRUE);
}
}