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;
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 aOnIdle
callback.