Delphi: SQL Query in Omni Parallel.foreach blocking main thread

282 Views Asked by At

I have a parallel.foreach loop which is blocking the interface from responding. In the loop I am calling a function which calls a mySQL stored procedure. I would like this to happen in the background but it restricts the UI from responding until all items in the loop are complete. The UI is responsive the the query is not executed. Is there a way to make sure that the sql call runs in the background and allow the user to proceed?

    Loop := Parallel.ForEach(1, L.Count - 1)
    .TaskConfig(Parallel.TaskConfig.OnMessage(Self))
    .NoWait
    .OnStop(
      procedure(const task: IOmniTask)
      begin
        task.Invoke(
          procedure
          begin
            wait.Signal;
            Loop := nil;
          end);
      end);
 
    loop.PreserveOrder;
    Loop.CancelWith(CancelToken);
    Loop.Into(outQueue).Execute(
      procedure(const task: IOmniTask; const Value: integer; var Result: TOmniValue)
      var
        E: TEmployee;
      begin
        task.Comm.Send(WM_LOG, value);
        E := L[Value];
        ProcessEmployee(E);
        Result := TEmployee.Create;
        TEmployee(Result).EmployeeID := E.EmployeeID;
      end);

      wait.WaitFor;

the loop calls the below function

    procedure TRun.ProcessEmployee(E: TEmployee);
    var
     Conn: TSQLConnection;
     MyQuery: TSQLQuery;
    begin
     Conn := CreateDatabase(nil);
     OpenDatabaseEx(Conn);
     MyQuery := CreateQuery(nil, Conn);
     try
      try
        //QueryHere
        MyQuery.ExecSQL();
        Application.ProcessMessages;
        E.Status := True;
      except
      on Exc: exception do
       begin
        exit;
       end;
      end;
    finally
     Conn.Free;
     MyQuery.Free;
     end;
    end;
1

There are 1 best solutions below

0
On

You are calling wait.WaitFor in the main thread. This prevents it from running (and, among others, processing UI events).

You should check for completion in a non blocking way. For example by checking the status of your wait condition in a OnIdle callback.