I have an app that uses TIdHTTPServer
to run a simple HTTP server on port 80. I'm using the OnCommandGet
event to get commands and return data using TClientDataSet
.
It works, but the problem is, this same app has visual components attached to the TClientDataSet
, like TDBGrid
.
And what is happening is, when OnCommandGet
changes TClientDataSet.CommandText
, the TDBGrid
needs to be updated and then weird things start to happen: the TDBGrid
starts to have glitches, the Form itself starts to behave strangely. After this happens, the only fix is to restart the application.
I know that probably this is because some thread is messing with visual components and I know I should avoid this by synchronizing the thread, but I don't know how to do this using TIdHTTPServer
.
Any help would be very appreciated, I'm having to restart my app several times during the day.
I know that probably this is because some thread is messing with visual components
Correct. TIdHTTPServer
is a multi-threaded component, its OnCommand...
events are fired in worker threads, so you must synchronize with the main UI thread when touching UI components.
I know I should avoid this by synchronizing the thread, but I don't know how to do this using
TIdHTTPServer
.
You synchronize with the main UI thread like with any other worker thread - by using the TThread.Synchronize()
or TThread.Queue()
method, or Indy's TIdSync
or TIdNotify
class. For example:
procedure TMyForm.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequeestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
...
TThread.Synchonize(nil, // or TThread.Queue()...
procedure
begin
...
ClientDataSet1.CommandText := ...;
...
end
);
...
end;
The alternative is to simply not touch the TClientDataSet
in the OnCommandGet
event at all. Give the thread its own dedicated connection to the database and use local components to query/update the data. Have the main thread use its own database connection when hooking up the TDGBrid
.