Lazarus

Programming => Operating Systems => Linux => Topic started by: userx-bw on January 30, 2014, 05:21:37 pm

Title: TProcess Thread handing HOW TO?
Post by: userx-bw on January 30, 2014, 05:21:37 pm
the External Program works with the code yet the button sticks in the down position and the form freezes.

Even though it is not in this code:

I've Placed the "Application.ProcessMessages" in various places trying to find where it should go, and nothing helps. I use this same code to set the Image and background colors without a loop so it just stays like that and I do not get this problem.

it is only when I put it in this loop that it causes the Button to stick in the down position while still running the external program in the loop like it is suppose to without errors, leaving the button stuck and
the form frozen on the screen.

I've tried to figure out all of the suggestions but I know  absolutely nothing about how to handle Threads.  Nor how to write what ever it is "they" show one in the examples, or what ever units or forms that needed to be used other then the main unit in order to know where to put whatever wherever it needs to be. They just confuse me as they are written for someone with more experience in programming then I.

This code here is where the code for the TProcess use to be.

I even used another TProcess component  and named it BProcess then I just kept all the error checking in there then took the code for the TProcess then put it into a procedure of its own, it runs properly the way it is suppose to run, still just leaving the form frozen with the Cycle_bn (TButton) stuck down.
 
Code: [Select]

procedure TForm1.Cycle_bnClick( Sender: TObject) ;
begin
   
     //if it has an Image check for Dimentions
   if (imgWidth_bx.Text = '') or (imgHeight_bx.Text = '') then
     if MessageDlg('Information', 'No Diamentions set', mtInformation, [mbCancel], 0) = mrCancel then
      abort;

   if (orgSRG.ItemIndex =-1) and (userSRG.ItemIndex =-1) then
    if MessageDlg('Information', 'No Background Set.', mtInformation, [mbCancel],0)= mrCancel then
    abort;

   if IsValidEntry(imgHeight_bx.Text) then  ImgHeight := imgHeight_bx.Text ;
   if IsValidEntry(imgWidth_bx.Text)  then  ImgWidth := imgWidth_bx.Text;
      // cantanates the two valaues and adds the x between them
      // image size and formats to numberXnumber
      ImgWidth += 'x' + ImgHeight;

    if ColorsGB.Enabled then
      SetColors;

     // set milliseconds to minutes
   cycleimage := (CycleTS.Value * 1000 * 60);

   FindImageFiles := FindAllFiles(chosenDirectory, '*.*', false);
   FindImageFiles.Sort;

  CycleBG( SetColorsRG, tint_cb, blur_cb, Sharp_cb, contrast_cb, Bright_cb,
           gamma_cb, alpha_cb, FlipBgRg, orgSRG, UserSRG);


end;


This is the code for the TProcess. I took out a lot of it to make it
easer to read. Leaving the major parts.

Code: [Select]

procedure CycleBG( SetColorsRG: TRadioGroup ; tint_cb: TCheckBox ; blur_cb: TCheckBox ;
  Sharp_cb: TCheckBox ; contrast_cb: TCheckBox ; Bright_cb: TCheckBox ;
  gamma_cb: TCheckBox ; alpha_cb: TCheckBox ; FlipBgRg: TRadioGroup ;
  orgSRG: TRadioGroup ; UserSRG: TRadioGroup);

begin

   i := 0;
   try
   while i < FindImageFiles.Count do
      begin
        if (CompareFileExt(FindImageFiles.Strings[i], 'jpg') = 0 ) or
           (CompareFileExt(FindImageFiles.Strings[i], 'png') = 0 )
            then
             begin
                BProcess := TProcess.Create(nil);
                BProcess.Executable:= 'mhsetroot';

               if SetColorsRG.ItemIndex > -1 then
               begin
                case SetColorsRG.ItemIndex of
               ........
                 end;
           end; //end case
        end;

    if tint_cb.Checked then
    begin
    .........
    end;

    if orgSRG.ItemIndex > -1 then
    case orgSRG.ItemIndex of
        ..........
    end;

    if UserSRG.ItemIndex > -1 then
    case userSRG.ItemIndex of
       ...........
    end;

        BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
       
        BProcess.Execute;

        BProcess.Free;

        sleep(cycleimage);
       
   end; //end compare file types
       
        i := i + 1;
       
        // keep cycling through images
        if i = FindImageFiles.Count then i := 0;
       
     end; // end while loop
   finally
      FindImageFiles.Free;
   end;
end;


all vaiabales have been declaried in the var aera.
Title: Re: TProcess Thread handing HOW TO?
Post by: cdbc on January 30, 2014, 08:54:38 pm
Hi
It could be an infinite loop, maybe in your while section, do you remember to incement i ?
Regards Benny
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on January 30, 2014, 09:32:19 pm
Hi
It could be an infinite loop, maybe in your while section, do you remember to incement i ?
Regards Benny

Yeah it is right here at the bottom of my code, because it has to be in an infinite Loop.

Quote
  i := i + 1;
       
        // keep cycling through images
        if i = FindImageFiles.Count then i := 0;

Title: Re: TProcess Thread handing HOW TO?
Post by: Leledumbo on January 31, 2014, 04:36:51 am
Quote
BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
       
        BProcess.Execute;
Well, what do you expect? You have an infinite loop executing external process in a single (main) thread. Of course your form will freeze. If you want something that keeps working behind the scene while you still can work on the main UI then use a thread (which may have process execution inside). Take a look at how (ridiculous, but working) I implement such a functionality to one of my apps (https://bitbucket.org/leledumbo/express).
Title: Re: TProcess Thread handing HOW TO?
Post by: User137 on January 31, 2014, 11:23:21 am
1 way to make repeating loop is like this:
Code: [Select]
i:=0;
while true do begin
  // .. do something

  i:=(i+1) mod n; // Will keep i between 0..n-1
end;
You need exit condition for your loop though, if using a thread, you can terminate it from outside (like some button tells thread.Terminate;) and changing loop to:
Code: [Select]
repeat
...
until Terminated;
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on January 31, 2014, 02:19:49 pm
Quote
BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
       
        BProcess.Execute;
Well, what do you expect? You have an infinite loop executing external process in a single (main) thread. Of course your form will freeze. If you want something that keeps working behind the scene while you still can work on the main UI then use a thread (which may have process execution inside). Take a look at how (ridiculous, but working) I implement such a functionality to one of my apps (https://bitbucket.org/leledumbo/express).


the Script that I wrote to do the very same thing does not have this problem, but everybody wants a GUI in linux, they get away from Windows and get Linux and still want everything to be like Windows. go get windows people ....   :-[

so yeah with

Script: eternal loop no freezing up it just works.
GUI:    eternal loop freezing up it doesn't work.

So that is my problem I have no idea how to deal with a thread. I just started programming, with not a whole lot of experience time under my belt, and the examples that I have found with Google do not help me as they are written for someone that knows how to deal with threads or has more knowledge of an OS and how they work then I do.


what I have tried when dealing with a thread just crashed it and such.

MOD: ADDED:

I am researching this fork thing and threads. is that a good idea?




Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on January 31, 2014, 04:24:49 pm
Quote
1 way to make repeating loop is like this:
Code: [Select]
i:=0;
while true do begin
  // .. do something

  i:=(i+1) mod n; // Will keep i between 0..n-1
end;


whats n?
besides a variable not declared.
Title: Re: TProcess Thread handing HOW TO?
Post by: snorkel on January 31, 2014, 04:41:20 pm
do the loop in a thread object.
I do endless loops in threads for TCP/IP servers all the time.

Just use a While not terminated do

You should also use a sleep in your loop or it will consume all the CPU cycles.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on January 31, 2014, 05:31:57 pm
do the loop in a thread object.
I do endless loops in threads for TCP/IP servers all the time.

Just use a While not terminated do

You should also use a sleep in your loop or it will consume all the CPU cycles.

well I do have the sleep within the loop that too was something I didn't understand as it stops the loop therefore stops using the CPU cycles to run the loop. as the loop only runs once then sleeps for a minute min time before it runs again.

well I guess I just got a "Google learn" how to do that now  :o  :D
thanks
Title: Re: TProcess Thread handing HOW TO?
Post by: Leledumbo on February 01, 2014, 12:08:06 am
Quote
BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
       
        BProcess.Execute;
Well, what do you expect? You have an infinite loop executing external process in a single (main) thread. Of course your form will freeze. If you want something that keeps working behind the scene while you still can work on the main UI then use a thread (which may have process execution inside). Take a look at how (ridiculous, but working) I implement such a functionality to one of my apps (https://bitbucket.org/leledumbo/express).


the Script that I wrote to do the very same thing does not have this problem, but everybody wants a GUI in linux, they get away from Windows and get Linux and still want everything to be like Windows. go get windows people ....   :-[

so yeah with

Script: eternal loop no freezing up it just works.
GUI:    eternal loop freezing up it doesn't work.

So that is my problem I have no idea how to deal with a thread. I just started programming, with not a whole lot of experience time under my belt, and the examples that I have found with Google do not help me as they are written for someone that knows how to deal with threads or has more knowledge of an OS and how they work then I do.


what I have tried when dealing with a thread just crashed it and such.

MOD: ADDED:

I am researching this fork thing and threads. is that a good idea?
my app works at least on windows and linux, and I dare to say it would work on Mac as well. No problem with OS if you know how to work with TThread correctly.

Don't use fork for cross platform app, it's available on *nix only (though some morons write "cross platform" apps with it with the help of cygwin), TProcess wraps fork on *nix and CreateProcess on windows so it's all you need, you just have to figure out how to use it correctly along with TThread (again, see my app).
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 03:54:36 pm
my app works at least on windows and linux, and I dare to say it would work on Mac as well. No problem with OS if you know how to work with TThread correctly.

Don't use fork for cross platform app, it's available on *nix only (though some morons write "cross platform" apps with it with the help of cygwin), TProcess wraps fork on *nix and CreateProcess on windows so it's all you need, you just have to figure out how to use it correctly along with TThread (again, see my app).

are you taking about this code?

https://bitbucket.org/leledumbo/express/src/4a077d0e75fb1223ca3bcbb6b6a80bdf0083e45f/src/include/linux/browserdetection.inc?at=default


and No I have no idea about how to handle a Thread, yet TProcess is a Thread and others keep advising me to put TProcess into a Thread. That confuses me as it seems to take away the ability to use the TProcess.Parameters.Add () ?

I am thinking of trying to split it up and to figure out how to use the TTimer or just use the SLEEP(time), function then put the find file in a loop then  call the procedure to use the TProcess code then have it load from there, putting just the find file loop in a sleep state instead of having the find file and Tprocess in a loop and putting everything to sleep and see what that does.

from looking at your code it is not in a loop when you call to create a TProcess. it is a straight call to create it then execute it the free it.

where I am finding the file then creating a TProcess, executing it, freeing it, then finding the next file ,creating TProcess , executing it, then freeing it within the loop. If I figure out how to take the TProcess out of the loop and just send it a file to load that may help.


Quote
BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
I took that out.

as well as I tried using the TProcess.suppend and TProcess resume and it freed up the button but the form itself is still sucking up too many resources so it does not refresh until it sets another image to the desktop then it will refresh then freeze up again.
Title: Re: TProcess Thread handing HOW TO?
Post by: Rails on February 01, 2014, 04:27:54 pm

So that is my problem I have no idea how to deal with a thread. I just started programming, with not a whole lot of experience time under my belt, and the examples that I have found with Google do not help me as they are written for someone that knows how to deal with threads or has more knowledge of an OS and how they work then I do.


what I have tried when dealing with a thread just crashed it and such.

MOD: ADDED:

I am researching this fork thing and threads. is that a good idea?

It seems like you are beating your head against the wall.

If you just started programming, why are you trying to deal with advanced subjects, such as threads and processes? I've been programming for my own purposes on and off since the late 1970's. I have never had to concern myself with threads or processes, beyond knowing what they are through osmosis, so to speak. The Lazarus IDE handles all that stuff for you, for all but the most sophisticated applications.

Why not give the folks here the big picture first? Tell them what you want to accomplish, starting with the intended purpose of the application itself, and let them suggest a good approach for a beginning programmer.  It will be whole lot less painful than what you are doing now.

Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 05:42:56 pm

So that is my problem I have no idea how to deal with a thread. I just started programming, with not a whole lot of experience time under my belt, and the examples that I have found with Google do not help me as they are written for someone that knows how to deal with threads or has more knowledge of an OS and how they work then I do.


what I have tried when dealing with a thread just crashed it and such.
I changed the files to txt extension

MOD: ADDED:

I am researching this fork thing and threads. is that a good idea?

It seems like you are beating your head against the wall.

If you just started programming, why are you trying to deal with advanced subjects, such as threads and processes? I've been programming for my own purposes on and off since the late 1970's. I have never had to concern myself with threads or processes, beyond knowing what they are through osmosis, so to speak. The Lazarus IDE handles all that stuff for you, for all but the most sophisticated applications.

Why not give the folks here the big picture first? Tell them what you want to accomplish, starting with the intended purpose of the application itself, and let them suggest a good approach for a beginning programmer.  It will be whole lot less painful than what you are doing now.

I keep beating my head on the wall over threads because everyone keeps telling me that if I put this code which works with no problems other then it locks up the GUI had or should be put into a thread in order for it to stop locking up the GUI (form).

Quote
Why not give the folks here the big picture first?
I forked a program called hsetroot added more features to it like being able to tell the program what size you want the image and how to set it on the desktop, then  renamed it mhsetroot put it in sourceforge. It is a Linux command line program that sets the background image and colors to your desktop.

I wrote a script for it with a loop in it that changes the images and colors on the desktop  at a given time, and adding in the script the ability to be able to change the time that you wanted the image and colors to change just by using the command line.

then came the GUI so I could learn how to do that now.

I chose Lazarus because it had drop the stuff you need on a form easyness,  and I found that they have the TProcess to use command line programs in Linux trough Lazarus therefore I need to use the TProcess. therefore it met my needs to be able to write a GUI that can use my command line program I wrote/added to.

I already wrote the program in Lazarus to do everything you can do with mhsetroot,  but the changing the image and colors on the background at a given time, called it gmhsetroot, then I put that up in sourcefouge.

then comes my next challenge, making it do what I did with the script. What I am now trying to do now by adding the ability to be able to have the image and colors change on the desktop at a given time that the user sets.

I did it with the images so far, I can watch it change the image on the background at the given time it is suppose to, but giving me this  problem of the button I clicked to make it do that freezing up then I got it to not do that then found that the form freezes up too. It works no problem, as it changes the image at the given time, but leaving the form froze and not refreshing. in other words it is when you run out of memory and that window just goes blank not seeing any buttons just the gray colored from. you can still move it all around the screen just no longer see any buttons and such.

that is one problem I have yet to tackle and writing the code to change the colors, and  the other is killing everything when I close the form to free up the TProcess so the form closes properly. as I keep getting some errors when I close it, that I have not paid much mind to as I am dealing with this one first, and that is about all I have left to do off the top of my head to get this "upgrade' done.
 

in my first post  it was suggested that I just put that into a thread and then it would just work. As I have no idea how to deal with threads, but if that is all I can do to get this to work then I have to use a thread, but TProcess is a Thread or has Thread Properties as it has suspend and resume. therefore a thread.

it seems that I have to deal with a Thread due to the nature of my program needing to use a loop so that it can cycle through the images and pick a different one (and colors too) then call the external program mhsetroot and have it set / change the image and colors on the desktop.

Because from what I understand that putting things in loops when using a GUI just eats up resources that is why it is locking up even though within the loop I put it to sleep.

Here is all of my CODE that has to do with this, as this form only allows so much to be written within a post I give it to all to read in a file to download, everything I have written thus far pertaining to my program mhsetroot, gmhsetroot. ie. the Big Picture.


I hope that is enough information. they are in "txt"


mod:
 actually I need to not really close the program  but be "hidden" so that the program if it is set to change the image and color to stay running in order to keep the TProcess running to change the image and colors(in random order). I just haven't gotten that far yet.
Title: Re: TProcess Thread handing HOW TO?
Post by: Leledumbo on February 01, 2014, 07:27:06 pm
Quote
are you taking about this code?

https://bitbucket.org/leledumbo/express/src/4a077d0e75fb1223ca3bcbb6b6a80bdf0083e45f/src/include/linux/browserdetection.inc?at=default
No, this one:
https://bitbucket.org/leledumbo/express/src/4a077d0e75fb1223ca3bcbb6b6a80bdf0083e45f/src/FormMain.pp?at=default
See TUPXThread and TUPXThreadRunner classes. TUPXRunner is a thread which will create a pool of threads executing TProcess.
Quote
and No I have no idea about how to handle a Thread, yet TProcess is a Thread and others keep advising me to put TProcess into a Thread. That confuses me as it seems to take away the ability to use the TProcess.Parameters.Add () ?
No, you mix up processes and threads. They are NOT the same. Process does contain at least one (main) thread, and may create more threads. If you have a quite advanced task manager or similar app, you can see child process when you create a process from your program, but you can't see your threads. Contrary to processes, threads don't have process ID, they live in the same address space as the main program.
Quote
I am thinking of trying to split it up and to figure out how to use the TTimer or just use the SLEEP(time), function then put the find file in a loop then  call the procedure to use the TProcess code then have it load from there, putting just the find file loop in a sleep state instead of having the find file and Tprocess in a loop and putting everything to sleep and see what that does.
TTimer won't help, even it could make things worse. TTimer.OnTimer is not exclusively locked, when it's time to enter the event, it will enter. If the previous code is not yet finished, it will still be executed. Not just your program, but the whole OS might be locked up (though modern OSes are smart enough to kill processes that don't answer signal because it eats too much CPU).
Quote
where I am finding the file then creating a TProcess, executing it, freeing it, then finding the next file ,creating TProcess , executing it, then freeing it within the loop. If I figure out how to take the TProcess out of the loop and just send it a file to load that may help.
You still have single threaded programming mind, you're not ready for multithreaded one. Read up and understand the concept first, you can't code advanced things without understanding how things work in the background. The relevant wiki article also has information about the limitation of threads and GUI.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 07:48:51 pm
Quote
are you taking about this code?

https://bitbucket.org/leledumbo/express/src/4a077d0e75fb1223ca3bcbb6b6a80bdf0083e45f/src/include/linux/browserdetection.inc?at=default
No, this one:
https://bitbucket.org/leledumbo/express/src/4a077d0e75fb1223ca3bcbb6b6a80bdf0083e45f/src/FormMain.pp?at=default
See TUPXThread and TUPXThreadRunner classes. TUPXRunner is a thread which will create a pool of threads executing TProcess.
Quote
and No I have no idea about how to handle a Thread, yet TProcess is a Thread and others keep advising me to put TProcess into a Thread. That confuses me as it seems to take away the ability to use the TProcess.Parameters.Add () ?
No, you mix up processes and threads. They are NOT the same. Process does contain at least one (main) thread, and may create more threads. If you have a quite advanced task manager or similar app, you can see child process when you create a process from your program, but you can't see your threads. Contrary to processes, threads don't have process ID, they live in the same address space as the main program.
Quote
I am thinking of trying to split it up and to figure out how to use the TTimer or just use the SLEEP(time), function then put the find file in a loop then  call the procedure to use the TProcess code then have it load from there, putting just the find file loop in a sleep state instead of having the find file and Tprocess in a loop and putting everything to sleep and see what that does.
TTimer won't help, even it could make things worse. TTimer.OnTimer is not exclusively locked, when it's time to enter the event, it will enter. If the previous code is not yet finished, it will still be executed. Not just your program, but the whole OS might be locked up (though modern OSes are smart enough to kill processes that don't answer signal because it eats too much CPU).
Quote
where I am finding the file then creating a TProcess, executing it, freeing it, then finding the next file ,creating TProcess , executing it, then freeing it within the loop. If I figure out how to take the TProcess out of the loop and just send it a file to load that may help.
You still have single threaded programming mind, you're not ready for multithreaded one. Read up and understand the concept first, you can't code advanced things without understanding how things work in the background. The relevant wiki article also has information about the limitation of threads and GUI.

aaahh SO you do put the TProcess inside the thread and then the thread just handles it. (?)

just call Thread.Create(true) in a suspended state suspending the TProcess and when I need to use it just Thread execute then suspend it for the time limit I need then call resume to have it execute the TProcess again? 

I hope I got that logic right.
Title: Re: TProcess Thread handing HOW TO?
Post by: Leledumbo on February 01, 2014, 08:08:37 pm
Quote
aaahh SO you do put the TProcess inside the thread and then the thread just handles it. (?)
Yes
Quote
just call Thread.Create(true) in a suspended state suspending the TProcess and when I need to use it just Thread execute then suspend it for the time limit I need then call resume to have it execute the TProcess again?
Suspend and Resume will suspend and resume the thread, respectively. But I don't think it will suspend the underlying process. I don't know, you have to confirm that yourself. As you can see, I didn't create suspended thread. The threads are executed immediately after creation.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 08:47:35 pm
Quote
aaahh SO you do put the TProcess inside the thread and then the thread just handles it. (?)
Yes
Quote
just call Thread.Create(true) in a suspended state suspending the TProcess and when I need to use it just Thread execute then suspend it for the time limit I need then call resume to have it execute the TProcess again?
Suspend and Resume will suspend and resume the thread, respectively. But I don't think it will suspend the underlying process. I don't know, you have to confirm that yourself. As you can see, I didn't create suspended thread. The threads are executed immediately after creation.


I'm working on it now, just trying to figure out your layout in your form it is different.

Quote
unit FormMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ComCtrls, ExtCtrls, Buttons, FileUtil, IniPropStorage, ColorProgress;

type

  { TMainForm }

  TMainForm = class(TForm)
 ......
 
    procedure BtnAboutClick(Sender: TObject);
       
   
  private
    { private declarations }
    function FileAlreadyInList(const FilePath: String): Boolean;
    function AddFile(const FilePath: String): Boolean;
    procedure AddDir(Directory: String; Recursive: Boolean);
    procedure CheckAll(Checked: Boolean);
    procedure EnableControls(Enable: Boolean);
    procedure CleanProgressAndResult;

   
   
    you have your function and procedure headers names here,
    I keep getting errors forward deleclrations
   
   
Quote

  public
    { public declarations }
  end;

  { TUPXThread }

  TUPXThread = class(TThread)
  private
    { Private declarations }
    FIndex: Integer;
    FDoneCount: PInteger;
    FThreadCount: PInteger;
    FForm: TMainForm;
    FUPXCmd: String;
    FUPXArgs: TStrings;
    FResultMsg: String;
    procedure UpdateStatus;
  public
    property ResultMsg: String read FResultMsg;
    constructor Create(const AIndex: Integer;
      ADoneCount, AThreadCount: PInteger; AForm: TMainForm;
      const AUPXCmd: String; const AUPXArgs: TStrings);
    destructor Destroy; override;
    procedure Execute; override;
  end;

  { TUPXThreadRunner }

  TUPXThreadRunner = class(TThread)
  private
    FForm: TMainForm;
    FUPXFile: String;
  public
    constructor Create(AForm: TMainForm; const AUPXFile: String);
    procedure Execute; override;
  end;

then you do this again
Quote

var
  MainForm: TMainForm;

implementation

why are you making the MainForm a Variable?

this is just checking for the Pascal version, so no big deal in my case?
Quote

{$if FPC_FULLVERSION >= 20400}
  {$R *.lfm}
{$endif}

Quote
uses
  FormAdv, FormAbout, AppOptions, Helpers, StrUtils, SyncObjs, Process;

how do you know what or wich units to put in the two seperate uses areas?

then Thread Variables? how do I know what they are or do I have to worry about that as I am just using one thread where you are multiThreading

and I am finding that writing functions and procedures and where do  I put them so that when I call them I don't get I have no Idea what your taking about from the compiler errors

Quote

threadvar
  ListItemCS: TCriticalSection;

{ TMainForm functions/procedures }

function TMainForm.FileAlreadyInList(const FilePath: String): Boolean;
var
  i: Integer;
  begin
......
end;


why is that TMainForm then function name ? then further down you call it with out the TMainForm.FileAlreadyInList(data);


Quote
  if not FileAlreadyInList(FilePath) then begin
  ....
 
 
 
 
 is all the Thread code suppuse to go on the bottom of the page?
 
Quote



{ TUPXThread }

procedure TUPXThread.Execute;
var
  TempPos: LongWord;
begin
  with TProcess.Create(nil) do
    try
      ...
      except
        on e: Exception do
          FResultMsg := e.Message;
      end;
      Synchronize(@UpdateStatus);
    finally
      Free;
    end;
end;

procedure TUPXThread.UpdateStatus;
begin
  ListItemCS.Acquire;
  try
   ....
  finally
    ListItemCS.Release;
  end;
end;

constructors

Quote
constructor TUPXThread.Create(const AIndex: Integer; ADoneCount,
  AThreadCount: PInteger; AForm: TMainForm; const AUPXCmd: String;
  const AUPXArgs: TStrings);
begin
  FreeOnTerminate := True;
  FIndex := AIndex;
  FDoneCount := ADoneCount;
  FThreadCount := AThreadCount;
  FForm := AForm;
  FUPXCmd := AUPXCmd;
  FUPXArgs := AUPXArgs;
  Inc(FThreadCount^);
  inherited Create(False);
end;

that is just property setting I need, right. (perhaps a redundent question)

Quote

destructor TUPXThread.Destroy;
begin
  Dec(FThreadCount^);
end;

{ TUPXThreadRunner }

constructor TUPXThreadRunner.Create(AForm: TMainForm; const AUPXFile: String);



there you put the main form in the constructor, why is that needed.

Quote

initialization
{$if FPC_FULLVERSION < 20400}
  {$I FormMain.lrs}
{$endif}
  ListItemCS := TCriticalSection.Create;

finalization
  ListItemCS.Free;

end.

why is the initialization at the bottom?

I hope that is not too many questions for you.

thanks
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 10:57:27 pm
I rewrote starting all over with just the thread.
Code: [Select]
unit FormMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, process, FileUtil, Forms, Controls, Graphics, Dialogs,
  StdCtrls, LCLType, LCLIntf, ExtDlgs, Buttons, LCLProc, LazHelpHTML;


type
  TShowStatusEvent = procedure(Status: String) of Object;
  { TForm1 }

  TForm1 = class( TForm)
    Button1: TButton;
    Label1: TLabel;
    Process: TProcess;
    setImgDir_bn: TButton;
    procedure Button1Click( Sender: TObject) ;
    procedure setImgDir_bnClick( Sender: TObject) ;
  private
    { private declarations }
  public
    { public declarations }
  end;

  {CycleThread}

   CycleScreenThread = class(TThread)
    private
      FResultMsg: String;
      fStatusText : string;
      FOnShowStatus: TShowStatusEvent;
      procedure ShowStatus;
    protected
      procedure Execute; override;
    public
      Constructor Create(CreateSuspended : boolean);
      property ResultMsg: String read FResultMsg;
      property OnShowStatus: TShowStatusEvent read FOnShowStatus write FOnShowStatus;
    end;



var
  Form1: TForm1;
  chosenDir:string;
  FindImageFiles:TStringList;


implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.setImgDir_bnClick( Sender: TObject) ;
begin
    SelectDirectory(chosenDir,[sdPrompt],0);
    SetCurrentDir(ChosenDir);
    FindImageFiles := FindAllFiles(chosenDir, '*.*', false);
    FindImageFiles.Sort;
    Form1.Caption:=ChosenDir;
    Label1.Caption:=IntToStr(FindImageFiles.Count);
end;

procedure TForm1.Button1Click( Sender: TObject) ;
begin
               // CycleScreenThread.Start;
end;




constructor CycleScreenThread.Create(CreateSuspended : boolean);
 begin
   FreeOnTerminate := True;
   inherited Create(CreateSuspended);
 end;

 procedure CycleScreenThread.ShowStatus;
 // this method is executed by the mainthread and can therefore access all GUI elements.
 begin
   if Assigned(FOnShowStatus) then
   begin
     FOnShowStatus(fStatusText);
   end;
 end;

 procedure CycleScreenThread.Execute;
 var
 i:integer;
 begin
  with Tprocess.Create(nil) do
  try
    try
     i := 0;
       while i < FindImageFiles.Count do
      begin
        if (CompareFileExt(FindImageFiles.Strings[i], 'jpg') = 0 ) or
           (CompareFileExt(FindImageFiles.Strings[i], 'png') = 0 )
            then
             begin
                Executable:= 'mhsetroot';

                Parameters.Add('-center');
                Parameters.Add(FindImageFiles.Strings[i]);

               {  Commented out for testing }
               {
               if SetColorsRG.ItemIndex > -1 then
               begin
                case SetColorsRG.ItemIndex of
                 0:
                 begin
                      Parameters.Add('-solid');
                      Parameters.Add(addC1);
                 end;
                 1:
                 begin
                      Parameters.Add('-add');
                      Parameters.Add(addC1);
                      Parameters.Add('-add');
                      Parameters.Add(addC2);
                      Parameters.Add('-gradient');
                      Parameters.Add(intTostr(grad1));
                 end;
                 2:
                 begin
                      Parameters.Add('-add');
                      Parameters.Add(addC1);
                      Parameters.Add('-add');
                      Parameters.Add(addC2);
                      Parameters.Add('-gradient');
                      Parameters.Add(intTostr(grad1));
                      // add second gradient
                      Parameters.Add('-add');
                      Parameters.Add(addC3);
                      Parameters.Add('-add');
                      Parameters.Add(addC4);
                      Parameters.Add('-gradient');
                      Parameters.Add(intToStr(grad1));
                 end;
                 3:
                 begin
                      Parameters.Add('-addd');
                      Parameters.Add(addC1);
                      Parameters.Add(intToStr(alpha1));
                      Parameters.Add('-addd');
                      Parameters.Add(addC2);
                      Parameters.Add(intTostr(alpha2));
                      Parameters.Add('-gradient');
                      Parameters.Add(intToStr(grad1));
                 end;
                 4:
                 begin
                      Parameters.Add('-addd');
                      Parameters.Add(addC1);
                      Parameters.Add(intToStr(alpha1));
                      Parameters.Add('-addd');
                      Parameters.Add(addC2);
                      Parameters.Add(intToStr(alpha2));
                      Parameters.Add('-gradient');
                      Parameters.Add(intTostr(grad1));
                      //add second gradinet
                      Parameters.Add('-addd');
                      Parameters.Add(addC3);
                      Parameters.Add(intTostr(alpha1));
                      Parameters.Add('-addd');
                      Parameters.Add(addC4);
                      Parameters.Add(intToStr(alpha2));
                      Parameters.Add('-gradient');
                      Parameters.Add(intToStr(grad1));
                 end;
           end; //end case
        end;

    if tint_cb.Checked then
    begin
       Parameters.Add('-tint');
       Parameters.Add(addTint);
     end;
    if blur_cb.Checked then
    begin
       Parameters.Add('-blur');
       Parameters.Add(intTostr(blur));
    end;

    if sharp_cb.Checked then
    begin
       Parameters.Add('-sharpen');
       Parameters.Add(intTostr(sharpen));
    end;

    if contrast_cb.Checked then
    begin
       Parameters.Add('-contrast');
       Parameters.Add(intTostr(contrast));
    end;

    if bright_cb.Checked then
    begin
       Parameters.Add('-brightness');
       Parameters.Add(intToStr(brightness));
    end;

    if gamma_cb.Checked then
    begin
       Parameters.Add('-gamma');
       Parameters.Add(intToStr(gamma));
    end;

    if alpha_cb.Checked then
    begin
       Parameters.Add('-alpha');
       Parameters.Add(intToStr(alpha3));
    end;

    if FlipBgRG.ItemIndex > -1 then
    case FlipbgRg.ItemIndex of
     0: Parameters.Add('-flipv');
     1: Parameters.Add('-fliph');
     2: Parameters.Add('-flipd');
    end;

    if orgSRG.ItemIndex > -1 then
    case orgSRG.ItemIndex of
         0:
         begin
              Parameters.Add('-fs');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         1:
         begin
              Parameters.Add('-center');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         2:
         begin
              Parameters.Add('-fill');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         3:
         begin
              Parameters.Add('-fimgd');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         4:
         begin
              Parameters.Add('-fimgh');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         5:
         begin
              Parameters.Add('-fimgv');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         6:
         begin
              Parameters.Add('-tile');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         7:
         begin
              Parameters.Add('-tilev');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         8:
         begin
              Parameters.Add('-tileh');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         9:
         begin
              Parameters.Add('-tilehv');
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
    end;

    if UserSRG.ItemIndex > -1 then
    case userSRG.ItemIndex of
         0:
         begin
              Parameters.Add('-dcenter');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         1:
         begin
              Parameters.Add('-dfimgh');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         2:
         begin
              Parameters.Add('-dfimgv');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         3:
         begin
              Parameters.Add('-dfimgd');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         4:
         begin
              Parameters.Add('-dtile');
              Parameters.Add(imgWIdth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         5:
         begin
              Parameters.Add('-dtileh');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         6:
         begin
              Parameters.Add('-dtilev');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
         7:
         begin
              Parameters.Add('-dtilehv');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
    end;
       }
       {end of comment out code for now }


       // BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
        Execute;
        CycleScreenThread.Start;
         if ExitStatus <> 0 then begin
          with TStringList.Create do
            try
              LoadFromStream(StdErr);
              FResultMsg := Text;
            finally
              Free;
            end;
          end;
        Free;
        Application.ProcessMessages;
        sleep(3000);
        end; //end compaire file types
        i := i + 1;
        if i = FindImageFiles.Count then i := 0; // keep cycling through images
     end; // end while loop

    except
        on e: Exception do
          FResultMsg := e.Message;
      end;  // end second try

      finally
      Free;
      FindImageFiles.Free;
   end; //end first try

end;


end.

and I get this error trying to start the thread

Code: [Select]
formmain.pas(339,32) Error: Only class class methods, class properties and class variables can be accessed in class methods
Title: Re: TProcess Thread handing HOW TO?
Post by: taazz on February 01, 2014, 11:05:15 pm
And rightly so, CycleScreenThread is a class not an object. You have to create an object from it ee call CycleScreenThread.create somewhere in your code and save the reference to that object to a variable so that you can later on access the object to call start or free or hat ever needs to be called.

That is one of the reasons why it is customary to declare all our classes starting with the latter T so we know it is a type and not a variable you can call out of the blue.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 01, 2014, 11:33:43 pm
And rightly so, CycleScreenThread is a class not an object. You have to create an object from it ee call CycleScreenThread.create somewhere in your code and save the reference to that object to a variable so that you can later on access the object to call start or free or hat ever needs to be called.

That is one of the reasons why it is customary to declare all our classes starting with the latter T so we know it is a type and not a variable you can call out of the blue.
thanks

but lazarus example.
Code: [Select]

  constructor TMyThread.Create(CreateSuspended : boolean);
  begin
    FreeOnTerminate := True;
    inherited Create(CreateSuspended);
  end;

......
 var
    MyThread : TMyThread;
  begin
    MyThread := TMyThread.Create(True); // This way it doesn't start automatically
    ...
    [Here the code initialises anything required before the threads starts executing]
    ...
    MyThread.Start;
  end;

my code
Code: [Select]

var
  Form1: TForm1;
  chosenDir:string;
  FindImageFiles:TStringList;
  CycleScreenThread:TCycleScreenThread;     

.......

procedure TForm1.Button1Click( Sender: TObject) ;
begin

     CycleScreenThread = TCycleScreenThread.Create(true);
     CycleScreenThread.Start;
end;

.......

constructor CycleScreenThread.Create(CreateSuspended : boolean);
 begin
   FreeOnTerminate := True;
   inherited Create(CreateSuspended);
 end;         

my errors from my code
Code: [Select]

formmain.pas(73,57) Error: Illegal expression
formmain.pas(80,37) Error: class identifier expected
formmain.pas(82,20) Error: Identifier not found "FreeOnTerminate"
formmain.pas(83,14) Error: Methods can be only in other methods called direct with type identifier of the class
formmain.pas(83,14) Fatal: Syntax error, ";" expected but "identifier CREATE" found

it says that Create(true) is Illegal expression
Title: Re: TProcess Thread handing HOW TO?
Post by: taazz on February 01, 2014, 11:56:24 pm
you did not declare anywhere the  TCycleScreenThread instead you declared
Code: [Select]
CycleScreenThread = class(TThread)
..........
end;

So clean up your code I guess.

Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 12:04:40 am
you did not declare anywhere the  TCycleScreenThread instead you declared
Code: [Select]
CycleScreenThread = class(TThread)
..........
end;

So clean up your code I guess.

as in

Code: [Select]
var
CycleScreenThread:TCycleScreenThread;
?
because if that is a yes then it is up where I put my code last line on the var part making it global.
other then that I have no idea what you mean.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 12:25:26 am
you did not declare anywhere the  TCycleScreenThread instead you declared
Code: [Select]
CycleScreenThread = class(TThread)
..........
end;

So clean up your code I guess.

found the error I made had = and not :=
Code: [Select]
CycleScreenThread = class(TThread)
but now  it is blowing up
screen shot attached...
something about having more then one maybe
as in the debugger I stop it on the create call then it goes to the constructor and through it twice then I get this error , but I only call create once.

corrected:
actually it when  i click step into it jumps from the constructor line straight to the end, then it goes back to the constructor then into the call then it blows up.

Title: Re: TProcess Thread handing HOW TO?
Post by: taazz on February 02, 2014, 01:11:42 am
I think that's a linux problem you need to add the cthreads unit in the projects uses clause for this to work.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 01:13:38 am
well I got the thread error fixed now it does not like the loop

Code: [Select]
   while i < FindImageFiles.Count do
      begin                                             
it goes to the first part of this loop and its like it just skips over everything in between and straight down to this like where it give me an error message.

Code: [Select]
    if i = FindImageFiles.Count then i := 0; // keep cycling through images               

why would it skip what it is suppose to look at within the loop?
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 01:16:08 am
I think that's a linux problem you need to add the cthreads unit in the projects uses clause for this to work.
yep it was in there but like this
Code: [Select]
program gmhsetrootThread;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  cthreads, Interfaces, // this includes the LCL widgetset
  Forms, FormMain;     

so I just added it outside the IFDEF now I got another problem i was writing about when you posted your response.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 01:21:13 am
when you have two trys how is it suppose to go?

Code: [Select]
   try
        try

         finally
          end;
except
 end;
or
Code: [Select]
try
      try
       except
        end;
 finally
 end;
Title: Re: TProcess Thread handing HOW TO?
Post by: taazz on February 02, 2014, 01:37:23 am
both are accepted constructs what you need to do?
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 01:44:16 am
@Leledumbo
@taazz

now that I got a thread started it seems that it does not like my loop what is using an integer, because it just skips over what is in side of the loop creating the TProcess and executing it.

what I have going on here is a two part process.

part one, an array of image files that need to go through a loop to pick one out at a time then send to the TProcess then put into a wait state until said time elapses.

the second part is the TProcess that executes the Linux external program.

when the image  array is at the last element it has to be reset to the first element, so it can keep displaying images on the desktop.

It has to run the entire time until the user tells the program to stop changing the images on the desktop.

if I  remove the image loop then put it into a function then run it on a timer using sleep then send it to the thread so it can go into the TProcess to be executed that then now requires two threads and that sync thing has to be done and all that ????????

I am not sure of how to say it better.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 01:48:24 am
both are accepted constructs what you need to do?

I just copied a bit of someones code that they had me look at so I'd get the idea on how to run a thread and they had two tries in it so I just put them in there and at the bottom of my code it wants both the finally to free up what ever needs to be freed  and the except (on error) and I just want to be sure I had them in the right order is all. and now I got more problems if you could take a look at me last post in here.

thanks for you help btw
Title: Re: TProcess Thread handing HOW TO?
Post by: Leledumbo on February 02, 2014, 02:35:35 pm
I think talking about my code would be too broad, after all the thread support was not designed from the start, so I kinda hijack the code in order to make it work, which is why it looks ugly though works.

Let's just see your threading code now, the relevant parts only, of course. Though if you want, attaching a complete project source could help.
Title: Re: TProcess Thread handing HOW TO?
Post by: userx-bw on February 02, 2014, 03:55:52 pm
I think talking about my code would be too broad, after all the thread support was not designed from the start, so I kinda hijack the code in order to make it work, which is why it looks ugly though works.

Let's just see your threading code now, the relevant parts only, of course. Though if you want, attaching a complete project source could help.

any good or just starting programmer should know when to "hijack" code.  if it works then why waist all ones time in trying to reinvent another way of doing it? Just copy that code and incorporate it into what ever you are doing.

If someone is building something and finds that their is a part already made that he can use for what ever he is building the wise one would just go and get that part to use instead of waisting a lot of time trying to make one from scratch to use. It saves a lot of time and stress, and with some code it just has to be written a certain way in order for it to work, no matter what, the steps are all the same. so that is not really stealing code it is just the way it has to be done and copy and past is a lot faster the typing everything all out again, that is why they invented copy, and paste.

I do believe that is part of what this  GNU is about and  reusing code to falls into that ideology

mod:
added:
I put the thread code back inside of my whole program to see if I could get a bit further on it. I didn't data passing and it seeing the Objects like the RadioGroup it doesn't see or like the loop I had inside of it.

so this is as far as I got so far

both "programs" are in the first zip too

my code is me now stating the program all over again all over again so it is a shell of a program

mhsetroot the external program too if you have Linux then you can run my gmhsetroot to see it work too

you probably have to change the code a bit for it to see where mhsetroot is to run it

main form unit
Code: [Select]

type
       TShowStatusEvent = procedure(Status: String) of Object;
  { TForm1 }

  TForm1 = class( TForm)
    Button1: TButton;
    Label1: TLabel;
    Process: TProcess;
    setImgDir_bn: TButton;
    procedure Button1Click( Sender: TObject) ;
    procedure setImgDir_bnClick( Sender: TObject) ;
  private
    { private declarations }
  public
    { public declarations }

  end;
..........
var
  Form1: TForm1;
  //ImageFile:string;
  chosenDir:string;
  FindImageFiles:TStringList;
  // Threads
  CycleScreenThread:TCycleScreenThread;



implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.setImgDir_bnClick( Sender: TObject) ;
begin
    SelectDirectory(chosenDir,[sdPrompt],0);
    SetCurrentDir(ChosenDir);
    //TStringList
    FindImageFiles := FindAllFiles(chosenDir, '*.*', false);
    FindImageFiles.Sort;
    Form1.Caption:=ChosenDir;
    Label1.Caption:=IntToStr(FindImageFiles.Count);
end;

procedure TForm1.Button1Click( Sender: TObject) ;
begin
   // FindImage(FindImageFiles);

    CycleScreenThread := TCycleScreenThread.Create(true) ;
    CycleScreenThread.Start;

end;
                                       




that is the thread unit
Code: [Select]
unit Onethread;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, process, LCLType,
  LCLIntf, ExtDlgs, Buttons, LCLProc, LazHelpHTML, FileUtil;
  {CycleThread}
     type
        TShowStatusEvent = procedure(Status: String) of Object;


   TCycleScreenThread = class(TThread)
    private
      FResultMsg: String;
      fStatusText : string;
      FOnShowStatus: TShowStatusEvent;
      procedure ShowStatus;
    protected

      procedure Execute; override;
    public
      Constructor Create(CreateSuspended : boolean);
      property ResultMsg: String read FResultMsg;
      property OnShowStatus: TShowStatusEvent read FOnShowStatus write FOnShowStatus;

 //      function FindImage(FindImageFiles: TStringList):string;
    end;

   var
    ImageFile:string;
  chosenDir:string;
  FindImageFiles:TStringList;

implementation



constructor TCycleScreenThread.Create(CreateSuspended : boolean);
 begin
   FreeOnTerminate := True;
   inherited Create(CreateSuspended);
 end;

{function goes here}

function FindImage(FindImageFiles: TStringList):string;
var
    i:integer;

begin
    i := 0;
    while i < FindImageFiles.Count do
      begin
        if (CompareFileExt(FindImageFiles.Strings[i], 'jpg') = 0 ) or
           (CompareFileExt(FindImageFiles.Strings[i], 'png') = 0 )
            then
            begin
             imageFile := FindImageFiles.Strings[i];
             result := ImageFile;
             i := i + 1;
             sleep(3000);
             end;
        if i = FindImageFiles.Count then i := 0;
      end;
 end;
 procedure TCycleScreenThread.ShowStatus;
 // this method is executed by the mainthread and can therefore access all GUI elements.
 begin
   if Assigned(FOnShowStatus) then
   begin
     FOnShowStatus(fStatusText);
   end;
 end;

 procedure TCycleScreenThread.Execute;
 var
 i:integer;
 begin
   try
          // function freezes up the whole systhem inm debug.

     //   ImageFile := form1.FindImage(FindImageFiles);
   //  while not Terminated do begin

              with Tprocess.Create(nil) do
               try
                begin
                Executable:= 'mhsetroot';

                Parameters.Add('-center');
                Parameters.Add(ImageFile);

               {  Commented out for testing }
               {
               if SetColorsRG.ItemIndex > -1 then
               begin
                case SetColorsRG.ItemIndex of
                 0:
                 begin
              .............
         end;
         7:
         begin
              Parameters.Add('-dtilehv');
              Parameters.Add(imgWidth);
              Parameters.Add(FindImageFiles.Strings[i]);
         end;
    end;
       }
       {end of comment out code for now }


       // BProcess.Options := BProcess.Options + [poWaitOnExit, poUsePipes];
       

          Execute;

         if ExitStatus <> 0 then begin
          with TStringList.Create do
            try
              LoadFromStream(StdErr);
              FResultMsg := Text;
            finally
              Free;
            end;
          end;
        Free;      // free process
     //  Application.ProcessMessages;
    //   sleep(3000);
        end;

                //end compaire file types
               finally
                free;
                end;
      except
        on e: Exception do
          FResultMsg := e.Message;
      end;  // end second try

      FindImageFiles.Free;
   end; //end first try

end.

I think now I am going to have to go with more then one thread , one for TProcess, one for getting a Image loop, and one for picking  one color, and one for picking two colors to be sent to the "main" thread running TProdcess making that 4 threads and 1 thread to keep track of them making it 5 so far. I only got one wrote up ...

the zip has all the code files and mhsetroot is you are using Linux to put in the code where that is and see how far I got because it calls it then clears the screen
TinyPortal © 2005-2018