1

This is my code:

procedure TfrmServerMain.CmdHndler_GetOrderProdDatesCommand(ASender: TIdCommand);
begin
  if Assigned(ASender.Params) then
    with TADOQuery.Create(nil) do
    begin
      Connection := ADOConnection1;

      SQL.Clear;
      SQL.Add('SELECT *');
      SQL.Add('FROM DoneOperations');
      SQL.Add('WHERE OrderID = ' + ASender.Params[0]);
      SQL.Add('ORDER BY DoneDate');

      try
        Open; // issued line

        if RecordCount = 0 then
        begin
          ASender.Context.Connection.Socket.WriteLn(FloatToStr(MaxDateTime), TIdTextEncoding.UTF8);
          ASender.Context.Connection.Socket.WriteLn(FloatToStr(MaxDateTime), TIdTextEncoding.UTF8);
        end
        else
        begin
          First;
          ASender.Context.Connection.Socket.WriteLn(
            FloatToStr(FieldByName('DoneDate').AsDateTime));

          Last;
          ASender.Context.Connection.Socket.WriteLn(
            FloatToStr(FieldByName('DoneDate').AsDateTime));
        end;
      except
        Log(ltError, 'Exception while sending Orders start/end date');
        ASender.Context.Connection.Socket.WriteLn('error');
        ASender.Context.Connection.Socket.WriteLn('error');
      end;

      Close;
      Free;
      ASender.Context.Connection.Disconnect;
    end;
end;

everything is ok, and code run correctly. but sometimes (20% of times) randomly when application execute Open; line, causes access violation error.

the SQL statement is tested separately, and works without any error in any condition. f.e.: SELECT * FROM DoneOperations WHERE OrderID = 35 ORDER BY DoneDate

OSs that I test: Windows7, Windows Server 2008.

I can't handle this, or find it's cause. thanks from your help.

Farshad H.
  • 303
  • 4
  • 16
  • Have you tried dropping the `TADOQuery` on the form, or a data module, instead of constantly creating and freeing it? – David A May 26 '15 at 05:20
  • 5
    Looks like this could be a threading issue. ADO Connection is not thread-safe, you need a separate instance for each thread, I think. – Ondrej Kelle May 26 '15 at 05:25
  • @DavidA No, I can't do that, because this routine is called from Client-Side many times. and every query must be unique at the time. If I use one ADO component, it cant be responsible asynchronously (thread like). – Farshad H. May 26 '15 at 05:35
  • @TOndrej What about using constant `ConnectionString` and assigning that on run-time to `ADOQury`? is this possible? – Farshad H. May 26 '15 at 05:37
  • 8
    Indy `CommandHandler`-based components are multi-threaded, where `OnCommand` is triggered in the worker thread of a socket connection. ADO is not thread-safe (it uses apartment-threaded COM objects internally), so you MUST `CoInitialize()` each `CommandHandler` thread and give it its own `TADOConnection` and `TADOQuery`. If you want to share a single `TADOConnection` across multiple `CommandHandler` threads, you have to `Synchronize()` to the main thread, or delegate to a dedicated thread, and have the main/delegate thread handle all of the ADO operations on behalf of the worker threads. – Remy Lebeau May 26 '15 at 05:38

0 Answers0