I use Indy 9 with Delphi 5. In my application I want to communicate with a network device via UDP. So I use UDPServer comp. in a class which is derived from TThread.
When I write similar to the following code then CPU usage is 100%.
in the thread :
while not terminated do begin if GetMessage(Msg, 0, 0, 0) then begin if Msg.message = WM_UDPMSG then Break else DispatchMessage(Msg); end; end;
and OnUDPRead event :
try // Processing the data here except PostThreadMessage(ThreadId, WM_UDPMSG, 0, 0); end;
When I use Sleep function in the while-do loop or in OnUDPRead event there is no change. Still the CPU usage is 100%.
My thread priority is Normal.
How can I solve my problem?
The problem you have is because you’re receiving the UDP data in the GUI thread, but want to process the data in another thread.
The real problem is that your trying to use a asynchronous component in a blocking way. The better solution would be to use a real blocking UDP communication library such as synapse. Then it’s very easy to just wait for new data to receive in your thread.
You could just write:
while not Terminated do begin BytesRead := FSocker.RecvBufferEx(@(Buffer0), BufferSize, Timeout); if (BytesRead = 0) then begin // continue or exit if the receiving Failed case FSocket.LastError of 0, WSAETIMEDOUT: Continue; WSAECONNRESET, WSAENETRESET, WSAENOTCONN, WSAECONNABORTED, WSAENETDOWN: begin CloseConnection; Exit; end; else CloseConnection; Exit; end; end; // process the data in the buffer end;
I’m not intimate with delphi code, but you are running a busy-wait mechanism which is grinding your CPU.
Introducing a sleep or a delay to the loop only hides the problem. I suggest using a better method for receiving your messages/events. Many solutions exist, like the observer-listener pattern, or thread wait and notify schemes.
Some helpful links in response to your comment:
1 You need a version of Indy newer than 126.96.36.199, I think. Older ones have show-stopping threading bugs. That includes all versions of Indy delivered with Delphi up to version 7.
2 Take a look at the sample code on how to work with Indy.
Is there a version of GetMessage which waits (blocks the thread) until a message arrives?
I don’t know the verison of GetMassage. But it declared in Windows.pas like this
function GetMessage; external user32 name 'GetMessageA';
This project is very big project. So updating Indy is difficult for me. But if you sure the problem is because of old version of Indy, I’ll update it.
I’ve looked at all Indy demos. These demos are very simple. In my project I’ve very fast data transfer. (Like real time sound recorder)