Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

100% CPU usage in Delphi

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?

like image 608
SimaWB Avatar asked Feb 04 '09 08:02

SimaWB


4 Answers

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(@(Buffer[0]), 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;
like image 151
Davy Landman Avatar answered Oct 26 '22 18:10

Davy Landman


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:
  • Thread wait-notify in delphi
  • Observer pattern
like image 42
Yuval Adam Avatar answered Oct 26 '22 16:10

Yuval Adam


1 You need a version of Indy newer than 9.0.0.18, 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.

http://www.indyproject.org/demos/index.html

like image 23
Stephan Eggermont Avatar answered Oct 26 '22 17:10

Stephan Eggermont


Is there a version of GetMessage which waits (blocks the thread) until a message arrives?

like image 24
James L Avatar answered Oct 26 '22 16:10

James L