Delphi ADO EDatabaseError connecting to access database from different threads

Viewed 115

I am attempting to open a connection to an Access database using a TADOConnection created on separate threads. On opening the connection an EDatabaseError 'External exception C06D007F' is thrown in Data.Win.ADODB. I tried searching and was only able to find examples adding calls to CoInitialize/CoUninitialize, and am not sure what else is wrong with my code. The same connection code succeeds when not executed in a TTask or TThread.

Update: The code works when I compile the test app with 32 bit, but fails with 64 bit. I have both Access 32 bit and 64 bit database engines installed on my computer. I uninstalled the 64 bit engine and reinstalled with the latest one from Microsoft and the errors went away.

  const
    ConnectionString: string = 'Provider=Microsoft.ACE.OLEDB.16.0;Data Source="C:\Users\Public\Documents\TestDatabase.mdb"';

  function TMainForm.CreateADOConnection(const AConnectionString: string): TADOConnection;
  begin
    Result := TADOConnection.Create(nil);
    Result.ConnectionString := AConnectionString;
    Result.LoginPrompt := False;
  end;

  procedure TMainForm.CreateDBConnections;
  var
    LTasks: array of ITask;
  begin
    SetLength(LTasks, 2);
  
    LTasks[0] := TTask.Create(procedure
    var
      LConn1: TADOConnection;
    begin
      CoInitialize(nil);
      try
        LConn1 := CreateADOConnection(ConnectionString);
        try
          LConn1.Open;
          LConn1.Close;
        finally
          LConn1.Free;
        end;
      finally
        CoUninitialize;
      end;
    end);

    LTasks[1] := TTask.Create(
    procedure
    var
      LConn2: TADOConnection;
    begin
      CoInitialize(nil);
      try
        LConn2 := CreateADOConnection(ConnectionString);
        try
          LConn2.Open;
          LConn2.Close;
        finally
          LConn2.Free;
        end;
      finally
        CoUninitialize;
      end;
    end);
  
    LTasks[0].Start;
    LTasks[1].Start;
  
    TTask.WaitForAll(LTasks);
  end;  

0 Answers
Related