Re: [lazarus] TRunInThread - Progress, but new problem

2006-03-05 Thread Michael Van Canneyt


On Sun, 5 Mar 2006, A.J. Venter wrote:

 On Sunday 05 March 2006 08:43, A.J. Venter wrote:
  Well since my last mail on this a few weeks ago, I have made quite a bit of
  progress in my attempts to create a component that will allow me to call a
  tprocess in a thread while retrieving the output live.
 
  The structure I have no compiles, and can be placed on a form - it is all
  but right. The only trouble is - when I call the run method, it throws an
  access violation, the stack trace places it at line 76 (the line where I
  call FProcessThread.resume), I did a check and the first line of the
  execute method does not ever get executed.
 
 Mmmm, I think I know now why this is happening, though now I have even LESS of
 an idea how to prevent it.
 I instantiated TProcessThread directly in a test program (obviously this left
 me with no events or such but I was just trying to see if it worked) when I
 call TProcessThread.Create the program dies with error 232 complaining that
 there isn't a thread driver.
 I checked the lpr, it calls cthreads. I checked lazarus.pp - that too calls
 cthreads, the only thing I can imagine is that I must somehow call cthreads
 in olpack, putting it in olpack.lpk doesn't work - lazarus recreates the file
 on compile/save apparently, putting it in runinthread.pas doesn't  work
 (probably because it's not early enough in the uses clause) - leaving me
 unable to determine where I SHOULD add it - or is this the IDE telling me
 that what I am trying to do is simply not possible ?

You should add it in the program file (.lpr) of your test program.
As the _first_ unit (possibly after cmem, if you use that too).

Michael.

_
 To unsubscribe: mail [EMAIL PROTECTED] with
unsubscribe as the Subject
   archives at http://www.lazarus.freepascal.org/mailarchives


Re: [lazarus] TRunInThread - Progress, but new problem

2006-03-05 Thread A.J. Venter

  I checked the lpr, it calls cthreads. I checked lazarus.pp - that too
  calls cthreads, the only thing I can imagine is that I must somehow call
  cthreads in olpack, putting it in olpack.lpk doesn't work - lazarus
  recreates the file on compile/save apparently, putting it in
  runinthread.pas doesn't  work (probably because it's not early enough in
  the uses clause) - leaving me unable to determine where I SHOULD add it -
  or is this the IDE telling me that what I am trying to do is simply not
  possible ?

 You should add it in the program file (.lpr) of your test program.
 As the _first_ unit (possibly after cmem, if you use that too).
It IS the first unit in the lpr :(
Could it be that it somehow just doesn't get compiled intoto the component  ?
Has anybody ever DONE a threaded component ?

A.J.
-- 
there's nothing as inspirational for a hacker as a cat obscuring a bug 
by sitting in front of the monitor - Boudewijn Rempt
A.J. Venter
Chief Software Architect
OpenLab International
www.getopenlab.com
www.silentcoder.co.za
+27 82 726 5103

_
 To unsubscribe: mail [EMAIL PROTECTED] with
unsubscribe as the Subject
   archives at http://www.lazarus.freepascal.org/mailarchives


[lazarus] TRunInThread - Progress, but new problem

2006-03-04 Thread A.J. Venter
Well since my last mail on this a few weeks ago, I have made quite a bit of 
progress in my attempts to create a component that will allow me to call a 
tprocess in a thread while retrieving the output live.

The structure I have no compiles, and can be placed on a form - it is all but 
right. The only trouble is - when I call the run method, it throws an access 
violation, the stack trace places it at line 76 (the line where I call 
FProcessThread.resume), I did a check and the first line of the execute 
method does not ever get executed.

At this stage the whole thing consists of two units. 
processthread.pas implements the TprocessThread class which is just a simple 
TThread descendent which runs a command.
TRunInThread is a TComponent descendent which encapsulates TProcessThread with 
a component, setting up an instantiation of it, executing it, storing and 
updating the output etc. 
In theory it should all work so I really do not know why it's throwing a 
trace, perhaps somebody else can tell me what to change ?

I attach both the units for your viewing pleasure.

-- 
there's nothing as inspirational for a hacker as a cat obscuring a bug 
by sitting in front of the monitor - Boudewijn Rempt
A.J. Venter
Chief Software Architect
OpenLab International
www.getopenlab.com
www.silentcoder.co.za
+27 82 726 5103
unit processthread;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,process;

Type
TProcessThread = class(tthread)
   protected
 procedure Execute; override;
   public
 fcommand : String;
 Constructor Create(isSuspended : boolean);
   end;

Var
   MemStream :TMemoryStream;
   Running:Boolean;

implementation

constructor TProcessThread.Create(isSuspended : boolean);
 begin
   MemStream := TMemoryStream.Create;
   inherited Create(isSuspended);
 end;

procedure TProcessThread.Execute;
const
  READ_BYTES = 2048;

Var
 Process :Tprocess;
  n: LongInt;
  BytesRead: LongInt;
begin
Process := TProcess.create(nil);;
 Process.CommandLine :=  Fcommand;
Running := True;


 {Actually run the thing and catch the output}
  BytesRead := 0;

Process.Options := [poUsePipes,poNoConsole];

  Process.Execute;

  while Process.Running do
  begin
// make sure we have room
MemStream.SetSize(BytesRead + READ_BYTES);

// try reading it
n := Process.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
if n  0
then begin
  Inc(BytesRead, n);
end
else begin
  // no data, wait 100 ms
  Sleep(100);
end;
  end;
  // read last part
  repeat
// make sure we have room
MemStream.SetSize(BytesRead + READ_BYTES);
// try reading it
n := Process.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
if n  0
then begin
  Inc(BytesRead, n);
end;
  until n = 0;
  MemStream.SetSize(BytesRead);
 Process.Free;
 Running := False;
end;

end.

unit RunInThread;

{$mode objfpc}{$H+}

interface

uses
  LResources,Classes, SysUtils,ProcessThread;

Type
TNewOutPutEvent = procedure(Sender: TObject;NewOutPut:TStringList) of object;
  
TRunInThread = Class(TComponent)
private
FOutPut : TStringList;
FNewOutPut :TStringlist;
FProcessThread : TProcessThread;
FCommand : String;
FRunning : Boolean;
FOnNewOuput : TNewOutPutEvent;
FOnDone : TNotifyEvent;
FLastSize : Integer;
FLastMSize : Integer;
procedure GetOutPut;
destructor destroy; override;
public
constructor Create(AOwner: TComponent);
procedure run;
published
property Command : String read FCommand write Fcommand;
property OutPut: TStringLIst read FOutput;
property Running: Boolean read FRunning;
property OnNewOutput : TNewOutPutEvent read FOnNewOuput write FOnNewOuput;
property OnDone : TNotifyEvent read FOnDone Write FOnDone;
end;

procedure Register;

implementation
procedure Register;
begin
  RegisterComponents('OLPack',[TRunInThread]);
end;

Constructor TRunInThread.Create(AOwner: TComponent);
Begin
  FLastSize := 0;
  FLastMSize := 0;
  FOutPut := TStringList.Create;
  FNewOutPut := TStringList.Create;
   FProcessThread := TProcessThread.Create(false);
   FProcessThread.FCommand := FCommand;
if Assigned(FProcessThread.FatalException) then
  raise FProcessThread.FatalException;
inherited create(AOwner);
end;

Destructor TRunInThread.Destroy;
Begin
 FProcessThread.Suspend;
 FOutPut.Free;
 FNewOutPut.Free;
 FProcessThread.Terminate;
 inherited destroy;
end;


Procedure TRunInThread.GetOutPut;
Begin
   FOutPut.LoadFromStream(MemStream);
end;

procedure TRunInThread.Run;
Var I : Integer;
Begin
  FProcessThread.Resume;
  FRunning := True;
  While Running do
  Begin
 If MemStream.Size  FLastMSize then
begin
 FLastMSize := MemStream.Size;
 GetOutPut;
 If 

Re: [lazarus] TRunInThread - Progress, but new problem

2006-03-04 Thread A.J. Venter
On Sunday 05 March 2006 08:43, A.J. Venter wrote:
 Well since my last mail on this a few weeks ago, I have made quite a bit of
 progress in my attempts to create a component that will allow me to call a
 tprocess in a thread while retrieving the output live.

 The structure I have no compiles, and can be placed on a form - it is all
 but right. The only trouble is - when I call the run method, it throws an
 access violation, the stack trace places it at line 76 (the line where I
 call FProcessThread.resume), I did a check and the first line of the
 execute method does not ever get executed.

Mmmm, I think I know now why this is happening, though now I have even LESS of 
an idea how to prevent it.
I instantiated TProcessThread directly in a test program (obviously this left 
me with no events or such but I was just trying to see if it worked) when I 
call TProcessThread.Create the program dies with error 232 complaining that 
there isn't a thread driver.
I checked the lpr, it calls cthreads. I checked lazarus.pp - that too calls 
cthreads, the only thing I can imagine is that I must somehow call cthreads 
in olpack, putting it in olpack.lpk doesn't work - lazarus recreates the file 
on compile/save apparently, putting it in runinthread.pas doesn't  work 
(probably because it's not early enough in the uses clause) - leaving me 
unable to determine where I SHOULD add it - or is this the IDE telling me 
that what I am trying to do is simply not possible ?

TIA
A.J.
-- 
there's nothing as inspirational for a hacker as a cat obscuring a bug 
by sitting in front of the monitor - Boudewijn Rempt
A.J. Venter
Chief Software Architect
OpenLab International
www.getopenlab.com
www.silentcoder.co.za
+27 82 726 5103

_
 To unsubscribe: mail [EMAIL PROTECTED] with
unsubscribe as the Subject
   archives at http://www.lazarus.freepascal.org/mailarchives