TurboPack/DOSCommand

Synchronization

ShadowOfStrelok7 opened this issue · 3 comments

Your component is awesome! But there is something I don't understand about synchronization.

I create a batch file inside my app and I redirect the output lines of the commands to a TListView. Everything works, excpet that lines appear in the TListView not synchronized! I mean: my code flow goes on after I run DOSCommand.Execute, but it doesn't wait for it to finish, so when other lines get added to the list (I use it as a log), at a certain point the output lines of the batch appear in the list view.

I just want that the batch file is executed and only AFTER my code flow continue! If I wouldn't be using your component I will run the batch with the API to wait for the process to finish.

Then, joined to this issues, there is this one: I found that if I execute with DOSCommand a command, then, again, it doesn't wait to it to be finished, so the next Execute rais an error saying that the previous command is still running! And if I add something like
while Self.DosCommand.IsRunning do Sleep(1000);
the process hangs forever, becuase IsRunning is always True, forever! I expected that after the command terminates IsRunning would return False.

What am I missing?

You have to use the OnNewLine event. This event is synchronized with the main thread.

You have to use the OnNewLine event. This event is synchronized with the main thread.

I'm already using it, but at the execution of the second command (ver) I get this error:
DosCommand still running.

This is the code, it's based on the Demo included in the source code you provide:

implementation

{$R *.dfm}

uses System.IOUtils;

procedure TForm4.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  Memo1.Lines.Clear;
  DosCommand1.CurrentDir := 'c:\windows';
  DosCommand1.CommandLine := 'cmd /c "dir"';
  DosCommand1.Execute;
  DosCommand1.CommandLine := 'cmd /c "ver"';  // this raises the error 'DosCommand still running'!
  DosCommand1.Execute;
end;

procedure TForm4.DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType);
begin
  if AOutputType = otEntireLine then
  begin
    Memo1.Lines.Add(ANewLine);
  end;
end;

procedure TForm4.DosCommand1Terminated(Sender: TObject);
begin
  Button1.Enabled := True;
end;

end.

Finally I solved it!

I was on the right way using this:
while Self.DOSCommand.IsRunning do Sleep(1000);
but it ended up in a never-ending loop:

so I ended up using a thread-safe version of that: Classes.CheckSynchronize:

  while Self.DOSCommand.IsRunning do begin
    CheckSynchronize(1000);
  end;