TProcess - Events?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Jay
Beiträge: 65
Registriert: Sa 29. Dez 2007, 02:21
OS, Lazarus, FPC: Linux, 0.9.30.4 Beta, FPC 2.6.0
CPU-Target: 32Bit
Kontaktdaten:

TProcess - Events?

Beitrag von Jay »

Hallo,

für mein Projekt "Cenonterix" verwende ich die Klasse TProcess, um die einzelnen Prozesse in den dafür vorgesehenen Objekten (TURLDownload, TFileConversion) zu handhaben. Da mehrere Prozesse nebeneinander laufen können, verwende ich Timer, die im Rhythmus von 1 Sekunde (nicht sehr Systemlastig) die Prozessüberwachung durchführen.

Meine Frage: gäbe es eine Möglichkeit, anstatt von Timern für die Prozessüberwachung auf Events zurückzugreifen? Habe bisher keine solche gefunden. Vielleicht stellt ja das System solche Events bereit?
Ich versuche es nach Möglichkeit zu vermeiden, über Timer zu arbeiten, da es eine nicht sehr elegante Lösung darstellt (nur, wenn es nicht anders geht).

Codeschnipsel 1:

Code: Alles auswählen

procedure TURLDownload.Start;
var
  InformationProcess: TProcess;
[...]
begin
[...]
  if (FStatus < 3) then begin
    FStatus := 3;
[...]
    FProcess := TProcess.Create(nil);
    FProcess.Options := [poUsePipes,poNoConsole];
    FProcess.CommandLine := CXMainForm.CScliveEdit.Text+' -q --output-file "'+FOutputDir+DirectorySeparator+FOutputFile+'" "'+FURL+'"';
    FProcess.Execute;
    FListItem.SubItems.Strings[0] := 'clive is downloading ...';
[...]
    FListItem.SubItems.Strings[1] := FOutputFile;
    FStatus := 4;
  end;
end;


Codeschnipsel 2:

Code: Alles auswählen

procedure TCXMainForm.CXDTimerTimer(Sender: TObject);
var
  I, A: Integer;
  ProcQueue: Integer;
  ProcCount: Integer;
  CanBeStarted: Array of TURLDownload;
  URLDownload: TURLDownload;
begin
  SetLength(CanBeStarted,0);
  ProcCount := 0;
  ProcQueue := 0;
  for I := 0 to CDList.Items.Count-1 do begin
    URLDownload := TURLDownload(CDList.Items.Item[I].Data);
    if (URLDownload.Status = 4) then begin
      URLDownload.Process;
      Inc(ProcCount);
    end else if (URLDownload.Status = 2) then begin
      A := Length(CanBeStarted);
      SetLength(CanBeStarted,A+1);
      CanBeStarted[A] := URLDownload;
      Inc(ProcQueue);
    end;
  end;
  I := 0;
  while (ProcCount+I < CSParallelDownloadsSpin.Value) and (I < Length(CanBeStarted)) do begin
    CanBeStarted[I].Start;
    Inc(I);
  end;
  CXStatus.Panels.Items[1].Text := 'Downloads: '+IntToStr(ProcCount)+'/'+IntToStr(ProcQueue);
  if (ProcCount+I <= 0) then
    CXDTimer.Enabled := False;
  SetLength(CanBeStarted,0);
end;
Codeschnipsel 3:

Code: Alles auswählen

procedure TURLDownload.Process;
begin
  if (FStatus = 4) then begin
    if (FProcess.Running = False) then begin
      if (FProcess.ExitStatus > 1) then begin
        Terminate(1);
        with FListItem.SubItems do begin
          Strings[0] := 'Failed!';
          Strings[1] := '';
        end;
        CXMainForm.CXTrayIcon.BalloonFlags:= bfError;
        CXMainForm.CXTrayIcon.BalloonHint := 'Download failed!'+#13#10+'URL: "'+FURL+'"';
        CXMainForm.CXTrayIcon.ShowBalloonHint;
        if (FOutputFile <> '') then
      end else begin
        Terminate(5);
        FListItem.SubItems.Strings[0] := 'Successful.';
        CXMainForm.CXTrayIcon.BalloonFlags:= bfInfo;
        CXMainForm.CXTrayIcon.BalloonHint := 'Download successful.'+#13#10+'URL: "'+FURL+'"';
        CXMainForm.CXTrayIcon.ShowBalloonHint;
        if (FConversionFile <> '') then
          CXMainForm.AddConversionToList(FOutputDir+DirectorySeparator+FOutputFile,FConversionFile);
      end;
    end;
  end;
end;
Codeschnipsel 4:

Code: Alles auswählen

procedure TURLDownload.Terminate(AStatus: Byte);
begin
  FStatus := AStatus;
  {$I-}
  if (FProcess <> nil) then begin
    if (FProcess.Running = True) then
      FProcess.Terminate(0);
    FProcess.Free;
    FProcess := nil;
  end;
  if (FStatus <> 5) and (FOutputFile <> '') and (FileExists(FOutputDir+DirectorySeparator+FOutputFile)) then
    DeleteFile(FOutputDir+DirectorySeparator+FOutputFile);
  {$I+}
end;
Edit: habe gerade gesehen, dass es neben dem "normalen" TProcess auch eine TAsyncProcess Komponente/Klasse gibt, welche ein OnTerminate-Event bereitstellt. Kann mir da bitte jemand näheres zu sagen?


Gruß

Jay

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: TProcess - Events?

Beitrag von _X_ »

Ich habe mal das hier gebastelt: http://www.lazarusforum.de/viewtopic.ph ... 96&start=0" onclick="window.open(this.href);return false;
Ich hoffe mal, das hilft dir weiter.

mfg _X_

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: TProcess - Events?

Beitrag von mschnell »

In syncobj sollte etwas zu finden sein.

Da es "procedure....message" gibt, wird es auch eine Möglichkeit geben, einem Message von einem Thread oder einer anderen Anwendung an den Mainthread zu senden.

-Michael

Jay
Beiträge: 65
Registriert: Sa 29. Dez 2007, 02:21
OS, Lazarus, FPC: Linux, 0.9.30.4 Beta, FPC 2.6.0
CPU-Target: 32Bit
Kontaktdaten:

Re: TProcess - Events?

Beitrag von Jay »

Danke erstmal für eure Antworten. Ich werde es erstmal so belassen, wie es jetzt ist.
Ich habe mal das hier gebastelt: viewtopic.php?f=29&t=2596&start=0
Ich hoffe mal, das hilft dir weiter.
Läuft im Endeffeckt auch wieder über einen 100ms Timer :wink:
In syncobj sollte etwas zu finden sein.
Hab mir das mal angesehen. Ist auch wieder was anderes, da dann zwar die Prozesse in Threads untergebracht wären (welche ich auch versuche zu vermeiden) aber die Events der einzelnen Prozesse/extern gestarteten Anwendungen/Commands würden mir dann trotzdem noch fehlen :roll:

Antworten