Recent

Author Topic: TThread questions  (Read 25682 times)

j0x

  • Full Member
  • ***
  • Posts: 126
TThread questions
« on: October 27, 2010, 05:09:31 pm »
ok its me again after reading this http://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial#The_TThread_Class as suggested earlier to me

i tried to make a TThread but i think its not working im on windows xp and im running a TProcess inside the execute procedure of TThread here are the codes that has importance to the problem

type area
Code: [Select]
type

    TMyThread = class(TThread)
    private
      fStatusText : string;
      procedure ShowStatus;
    protected
      procedure Execute; override;
    public
      Constructor Create(CreateSuspended : boolean);
      Hbk: TProcess;
      M: TmemoryStream;
      n: longInt;
      BytesRead: longInt;
    end;                     

implementation area
Code: [Select]
constructor TMyThread.Create(CreateSuspended : boolean);
  begin
    FreeOnTerminate := True;
    inherited Create(CreateSuspended);
  end;

  procedure TMyThread.ShowStatus;
  // this method is executed by the mainthread and can therefore access all GUI elements.
  begin
    frmMain.Caption := fStatusText;
  end;

 procedure TMyThread.Execute;
 begin

     Hbk.CommandLine := 'HandbrakeCLI -i ' + '"' + frmMain.txtInput.Text + '"' + ' -t 0';
     Hbk.Options := [poUsePipes, poStderrToOutPut];
     Hbk.ShowWindow := swoHide;
     Hbk.Execute;

     while Hbk.running do
     begin
          M.SetSize(BytesRead + READ_BYTES);
          n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
          if n > 0 then
          begin
               Inc(BytesRead,n);
               fStatusText := FormatDateTime('YYYY-MM-DD HH:NN:SS',Now);
               synchronize(@ShowStatus);
          end;
     end;

     repeat
           synchronize(@ShowStatus);
           M.SetSize(BytesRead + READ_BYTES);
           n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
           if n > 0 then
           begin
               Inc(BytesRead,n);
           end;
     until n <= 0;

     M.SetSize(BytesRead);
  end;               

frmMain area
Code: [Select]
procedure TfrmMain.btnScanClick(Sender: TObject);
begin
     if txtInput.Text = '' then exit;

     iThread.Resume;
     iThread.Execute;

     HbkStr.LoadFromStream(iThread.M);

     iThread.Terminate;

     mmoOutputs.Lines.Clear;
     mmoOutputs.Lines.BeginUpdate;
     mmoOutputs.Lines.AddStrings(Hbkstr);
     mmoOutputs.Lines.EndUpdate;

end;                 

i know its not good coding as i dont know classes much, but im wondering is there something wrong with my TThread coding? or windows xp just doesnt like Threading the StdErrOutput of Tprocess

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TThread questions
« Reply #1 on: October 27, 2010, 05:36:06 pm »
First, don''t call execute. Resume is starting the Thread if it was created Suspended.
Second you're treating the thread as if it was a blocking thing.
A thread has it's own life.
When you do

HbkStr.LoadFromStream(iThread.M);

It's absolutely not sure if the thread has already done it's job.
Use the OnTerminate event. Only then the thread has finished.

Maybe there are other issues, but these are the most important imho.

cdbc

  • Hero Member
  • *****
  • Posts: 1078
    • http://www.cdbc.dk
Re: TThread questions
« Reply #2 on: October 27, 2010, 08:14:29 pm »
Hi
@ Theo +1

@ios: complex topic :)
Have a look at this: http://www.midnightbeach.com/jon/pubs/MsgWaits/MsgWaits.html
or this: http://17slon.com/blogs/gabr/2010/03/omnithreadlibrary-105a.html

Btw. You don't check for "Terminated" in your 'Execute-method', so you can't terminate the thread before it's done! Please google "delphi threads" or so...

What about synchronizing variable access??? Or exception handling in the thread??? I would suggest you read up on your threading, as it is the deep end of the pool.

hth- Regards Benny
« Last Edit: October 27, 2010, 08:28:56 pm by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #3 on: October 28, 2010, 12:23:33 am »
thanks for the replies it now work when i call the resume method of tthread once now my question is how to call the execute of tthread again when i clicked the scan button here is the updated code

type area
Code: [Select]
type

    TMyThread = class(TThread)
    private
      fStatusText : string;
      procedure ShowStatus;
      procedure Scan;
    protected
      procedure Execute; override;
    public
      Constructor Create(CreateSuspended : boolean);
      Hbk: TProcess;
      M: TmemoryStream;
      n: longInt;
      BytesRead: longInt;
      doScan: boolean;
    end;            

implementation area
Code: [Select]
constructor TMyThread.Create(CreateSuspended : boolean);
  begin
    FreeOnTerminate := True;
    inherited Create(CreateSuspended);
  end;

  procedure TMyThread.ShowStatus;
  begin
    frmMain.Caption := fStatusText;
  end;

  procedure TMyThread.Scan;
  begin
     Hbk.CommandLine := 'HandbrakeCLI -i ' + '"' + frmMain.txtInput.Text + '"' + ' -t 0';
     Hbk.Options := [poUsePipes, poStderrToOutPut];
     Hbk.ShowWindow := swoHide;
     Hbk.Execute;

     while Hbk.running do
     begin
          M.SetSize(BytesRead + READ_BYTES);
          n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
          if n > 0 then
          begin
               Inc(BytesRead,n);
               fStatusText := FormatDateTime('YYYY-MM-DD HH:NN:SS',Now);
               synchronize(@ShowStatus);
          end;
     end;

     repeat
           synchronize(@ShowStatus);
           M.SetSize(BytesRead + READ_BYTES);
           n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
           if n > 0 then
           begin
               Inc(BytesRead,n);
           end;
     until n <= 0;

     M.SetSize(BytesRead);
     frmMain.HbkStr.LoadFromStream(M);

     frmMain.mmoOutputs.Lines.Clear;
     frmMain.mmoOutputs.Lines.BeginUpdate;
     frmMain.mmoOutputs.Lines.AddStrings(frmMain.Hbkstr);
     frmMain.mmoOutputs.Lines.EndUpdate;

     fStatusText := 'Finished';
     Synchronize(@ShowStatus);
  end;                          

frmMain area
Code: [Select]
procedure TfrmMain.btnScanClick(Sender: TObject);
begin
     iThread.doScan := true;
     iThread.Resume;
end;  

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  HbkStr := TStringList.Create;
  iThread := TMyThread.Create(True);
  iThread.M := TMemoryStream.Create;
  iThread.Hbk := TProcess.Create(nil);
  iThread.BytesRead := 0;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  iThread.Hbk.Free;
  HbkStr.Free;
  iThread.M.Free;
  iThread.Terminate;
  iThread.Free;
  inherited;
end;            

the btnScanClick on frmMain area is what i want to execute once the button is clicked again so ye thats my problem at the moment

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TThread questions
« Reply #4 on: October 28, 2010, 03:46:58 am »
Quote
how to call the execute of tthread again when i clicked the scan button here is the updated code
Don't set FreeOnTerminate to true and use this:
Code: [Select]
procedure TfrmMain.btnScanClick(Sender: TObject);
begin
    if iThread.Terminated then begin
      iThread.Execute;
    end else begin
      iThread.doScan := true;
      iThread.Resume;
    end;
end

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #5 on: October 28, 2010, 06:28:22 am »
@Leledumbo

ok ive set FreeOnTerminate to false
Code: [Select]
constructor TMyThread.Create(CreateSuspended : boolean);
  begin
    FreeOnTerminate := False;
    inherited Create(CreateSuspended);
  end;         

and set the Scan Click code to this
Code: [Select]
procedure TfrmMain.btnScanClick(Sender: TObject);
begin
     if iThread.Terminated = true then begin
        iThread.Execute;
     end else begin
        iThread.doScan := true;
        iThread.Resume;
     end;
end;           

but still no luck, the thread is still executing only once, and weird the Terminated property is not shown by Lazarus IDE when i put dot in the end of iThread word but it still compiled good so i guess Lazarus IDE just miss that Terminated property

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TThread questions
« Reply #6 on: October 28, 2010, 09:09:13 am »
I think you're over-complicating things.
Just create a new thread each time you need one. In your case, this should not be a performance problem.
Look, this is a very simple example of how I would do it:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     procedure Button1Click(Sender: TObject);
  17.     procedure ThreadTerminated(Sender: TObject);
  18.   private
  19.     { private declarations }
  20.   public
  21.     { public declarations }
  22.   end;
  23.  
  24.    { TMyThread }
  25.  
  26.    TMyThread = class(TThread)
  27.    private
  28.      FSomeInData: string;
  29.      FSomeOutData: string;
  30.    protected
  31.      procedure Execute; override;
  32.    public
  33.      property SomeOutData: string read FSomeOutData;
  34.      property SomeInData: string write FSomeInData;
  35.    end;
  36.  
  37.  
  38. var
  39.   Form1: TForm1;
  40.  
  41. implementation
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.Button1Click(Sender: TObject);
  48. var AThread:TMyThread;
  49. begin
  50.   AThread:=TMyThread.Create(True);
  51.   AThread.FreeOnTerminate:=true;
  52.   AThread.SomeInData:='Current Time ';
  53.   AThread.OnTerminate:=@ThreadTerminated;
  54.   AThread.Resume;
  55. end;
  56.  
  57. procedure TForm1.ThreadTerminated(Sender: TObject);
  58. begin
  59.   ShowMessage((Sender as TMyThread).SomeOutData);
  60. end;
  61.  
  62. { TMyThread }
  63.  
  64. procedure TMyThread.Execute;
  65. begin
  66.   Sleep(1000); //Wait a little
  67.   FSomeOutData:=FSomeInData+TimeToStr(Now);
  68. end;
  69.  
  70. end.
  71.  

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #7 on: October 28, 2010, 09:32:00 am »
oh creating a new thread each time, ye i thought i have to work on the same thread each time but then again when i click the scan button it seems that the thread is only executed once, so ye thanks for the tip on making a new thread each time i click scan, ill try it later

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #8 on: October 28, 2010, 01:05:50 pm »
seems working now thanks a lot theo now im gonna apply this to the main program im working with  :)

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #9 on: October 28, 2010, 01:48:50 pm »
im trying to apply what i learn on threading to the main program im working on
im getting this error:

Debugger Exception Notification
-------------------------------
raised exception class 'EThread' with message:
CheckSynchronize called from non-main thread '$460'

and here are some codes related to TThread
Code: [Select]
    scanThread.sPro := TProcess.Create(nil);
    scanThread.M := TMemoryStream.Create;
    scanThread.BytesRead := 0;
    scanThread.audioCount := 0;
    scanThread.i := 0;
    scanThread.scanned := false;
    //tmrScan.Enabled := true;
    btnEncode.Enabled := false;
    scanThread.Resume;

Code: [Select]
procedure TMyThread.Scan;
const
     READ_BYTES = 2048;
var
   x : integer;
   audioTracks: string;
begin
try
  audioTracks := '';

  frmMain.prgScan.StepIt;
  if frmMain.prgScan.Position = frmMain.prgScan.Max
    then frmMain.prgScan.Position := frmMain.prgScan.Min;

  if (scanned = false) and (i <= frmMain.lstAdd.Items.Count - 1) then
     begin
          sPro.CommandLine := 'HandbrakeCLI -i ' + '"' + frmMain.lstAdd.Items[i] + '"' + ' -t 0';
          sPro.Options := [poUsePipes, poStderrToOutPut];
          sPro.ShowWindow := swoShow;
          sPro.Execute;
          while sPro.running do
          begin
               M.SetSize(BytesRead + READ_BYTES);
               n := sPro.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
               if n > 0 then
               begin
                    Inc(BytesRead,n);
               end;
          end;

          repeat
                M.SetSize(BytesRead + READ_BYTES);
                n := sPro.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
                if n > 0 then
                begin
                     Inc(BytesRead,n);
                end;
          until n <= 0;

          M.SetSize(BytesRead);
          frmMain.HbkStr.LoadFromStream(M);

          if frmMain.HbkStr.IndexOf('No title found.') <> -1 then
             begin
             scanned := true;
             exit;
             end;

          audioCount := 0;
          x := frmMain.HbkStr.IndexOf('  + audio tracks:') + 1;
          repeat
                x := x + 1;
                AudioCount := AudioCount + 1;
          until (x = frmMain.HbkStr.Count - 1) or (x = frmMain.HbkStr.IndexOf('  + subtitle tracks:')) ;


          for x := 1 to AudioCount do begin
               audioTracks := audioTracks + intToStr(x);
               if x <> AudioCount then
                  audioTracks := audioTracks + ',';
          end;


          if frmMain.chkHardSubs.Checked = true then
          begin
                frmMain.lstOut.Items.add('HandbrakeCLI -i ' +  '"' + trim(frmMain.lstAdd.Items[i]) + '" ' + ' -f mkv -o ' +  '"' + trim(frmMain.lstAdd.Items[i]) + '-OUT.mkv' + '" '  + venString + trim(frmMain.txtVideoValue.Text) + ' -e x264 -x ' + x264String + ' -E vorbis -B '+ trim(frmMain.txtAudioValue.Text) + ' -w ' + trim(frmMain.txtWidth.Text) + ' -l ' + trim(frmMain.txtHeight.Text) + ' -s 1 --subtitle-burn 1' + ' -a ' + audioTracks);
          end
          else if frmMain.chkHardSubs.Checked = false then
          begin
                frmMain.lstOut.Items.add('HandbrakeCLI -i ' +  '"' + trim(frmMain.lstAdd.Items[i]) + '" ' + ' -f mkv -o ' +  '"' + trim(frmMain.lstAdd.Items[i]) + '-OUT.mkv' + '" '  + venString + trim(frmMain.txtVideoValue.Text) + ' -e x264 -x ' + x264String + ' -E vorbis -B '+ trim(frmMain.txtAudioValue.Text) + ' -w ' + trim(frmMain.txtWidth.Text) + ' -l ' + trim(frmMain.txtHeight.Text) + ' -a ' + audioTracks);
          end;

          scanned := true;
     end;

     if (scanned = true) and (i <= frmMain.lstAdd.Items.Count - 1) and (sPro.Running = false) then
     begin
          i := i + 1;
          scanned := false;
     end;

     if (scanned = false) and (i = frmMain.lstAdd.Items.Count)then
     begin
          //frmMain.tmrScan.Enabled := false;
          ShowMessage('Scanning Done');
          frmMain.btnEncode.Enabled := true;
          scanned := true;
          frmMain.prgScan.Position := frmMain.prgScan.Min;
          frmMain.lstAdd.Clear;
          frmMain.tbsOutput.Show;
          //sPro.Free;
          //M.Free;
     end;
except
      on E : Exception do ShowMessage(E.Message);
end;
end;         

and i got another question i cannot put the scanThread.Resume on a timer? in this case its called the tmrScan timer and if you notice i tried to capture the exact error message by try except method but no luck the error box just closes instantly the moment it shows up

any help or tips are much appreciated

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TThread questions
« Reply #10 on: October 28, 2010, 03:16:04 pm »
I don't really see how/where you call the Scan Method, but if it's in an unsynchronized  thread context, you simply can't access the MainForm from there without crashing.
Whenever you want to comunicate with the main thread, do it like you did with ShowStatus:
Synchronize(@ShowStatus);

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #11 on: October 28, 2010, 03:49:09 pm »
@theo

i call the scan method here procedure TfrmMain.btnEnqueueClick(Sender: TObject);
and this is the code
Code: [Select]
    scanThread.sPro := TProcess.Create(nil);
    scanThread.M := TMemoryStream.Create;
    scanThread.BytesRead := 0;
    scanThread.audioCount := 0;
    scanThread.i := 0;
    scanThread.scanned := false;
    //tmrScan.Enabled := true;
    btnEncode.Enabled := false;
    scanThread.Resume;
but my first attempt was on tmrScan onTimer event but it failed there too ok so im doing something wrong then like the synchronize method ill check to see what i could synchronize ill be back tomorrow

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TThread questions
« Reply #12 on: October 28, 2010, 04:08:31 pm »
I can't see where you call scan in the above snippet.
But as a rule of thumb you should not call any thread methods directly from the main thread.
Just call "Resume" this will call TMyThread.Execute and only from there you should do your thread-work which will be in the thread's context.
Access the result in the OnTerminate event handler.

j0x

  • Full Member
  • ***
  • Posts: 126
Re: TThread questions
« Reply #13 on: October 28, 2010, 04:30:44 pm »
here is the actual code of scan and scanThread is the TMyThread (TThread) and i called scanThread.Resume at the bottom

Code: [Select]
procedure TfrmMain.btnEnqueueClick(Sender: TObject);
var
  scanThread : TMyThread;
begin
  scanThread := TMyThread.Create(True);
  scanThread.venString := '';
  scanThread.x264String := '';

  if (cboMode.Text = 'CRF') and (txtVideoValue.Text <> '') then
  begin
   scanThread.venString := '-q ';
  end

  else if (cboMode.Text = 'Bitrate') and (txtVideoValue.Text <> '') then
  begin
    scanThread.venString := '-2 -b ';
  end

  else if (cboMode.text = 'File Size') and (txtVideoValue.Text <> '') then
  begin
    scanThread.venString := '-2 -S ';
  end;

  try
  if (strToInt(txtVideoValue.Text) < 10) and (cboMode.Text = 'CRF') then
  begin
    showmessage('CRF value must be >= 20 and <= 33');
    txtVideoValue.Text := '';
    txtVideoValue.SetFocus;
  end;
  except
    Exit;
  end;

  try
  if (strToInt(txtAudioValue.Text) < 10) then
  begin
    showmessage('Audio bitrate must be not less than 48');
    txtAudioValue.text := '';
    txtAudioValue.SetFocus;
  end;
  except
    Exit;
  end;

  if rbHigh.Checked = true then
    begin
    scanThread.x264String := 'deblock=1,1:ref=8:bframes=5:me=umh:subme=10:trellis=2:psy-rd=0.4:aq-strength=0.6:aq-mode=2';
    end
  else if rbMedium.Checked = true then
    begin
    scanThread.x264String := 'deblock=1,1:ref=5:bframes=3:me=umh:subme=8:trellis=1:psy-rd=0.4:aq-strength=0.6';
    end
  else if rbLow.Checked = true then
    begin
    scanThread.x264String := 'deblock=1,1:ref=3:bframes=3:trellis=1:psy-rd=0.4:aq-strength=0.6';
    end;

  if lstAdd.items.count = 0 then exit;

  if (txtVideoValue.text <> '') and (txtAudioValue.Text <> '') and (txtWidth.Text <> '') and (txtHeight.text <> '') then
  begin
    scanThread.sPro := TProcess.Create(nil);
    scanThread.M := TMemoryStream.Create;
    scanThread.BytesRead := 0;
    scanThread.audioCount := 0;
    i := 0;
    scanThread.scanned := false;
    //tmrScan.Enabled := true;
    btnEncode.Enabled := false;
    scanThread.Resume;
  end;

end;               

here is the Thread class now
Code: [Select]
TMyThread = class(TThread)
    private
      procedure Scan;
      procedure iUpdate;
      procedure prgUpdate;
    protected
      procedure Execute; override;
    public
      scanned: boolean;
      audioCount: integer;
      venString: string;
      x264String: string;
      sPro: TProcess;
      M: TmemoryStream;
      n: longInt;
      BytesRead: longInt;
    end;             

and i put synchronize action on the thread execute now
Code: [Select]
implementation

procedure TMyThread.Execute;
begin
     Scan;
end;

procedure TMyThread.iUpdate;
begin
     frmMain.i := frmMain.i + 1;
end;

procedure TMyThread.prgUpdate;
begin
   frmMain.prgScan.StepIt;
   if frmMain.prgScan.Position = frmMain.prgScan.Max
      then frmMain.prgScan.Position := frmMain.prgScan.Min;
end;   

procedure TMyThread.Scan;
const
     READ_BYTES = 2048;
var
   x : integer;
   audioTracks: string;
begin

  audioTracks := '';

  if (scanned = false) and (frmMain.i < frmMain.lstAdd.Items.Count) then
     begin
          sPro.CommandLine := 'HandbrakeCLI -i ' + '"' + frmMain.lstAdd.Items[frmMain.i] + '"' + ' -t 0';
          sPro.Options := [poUsePipes, poStderrToOutPut];
          sPro.ShowWindow := swoShow;
          sPro.Execute;
          while sPro.running do
          begin
               M.SetSize(BytesRead + READ_BYTES);
               n := sPro.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
               if n > 0 then
               begin
                    Inc(BytesRead,n);
                    Synchronize(@prgUpdate);
               end;
          end;

          repeat
                Synchronize(@prgUpdate);
                M.SetSize(BytesRead + READ_BYTES);
                n := sPro.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
                if n > 0 then
                begin
                     Inc(BytesRead,n);
                end;
          until n <= 0;

          M.SetSize(BytesRead);
          frmMain.HbkStr.LoadFromStream(M);

          if frmMain.HbkStr.IndexOf('No title found.') <> -1 then
             begin
             scanned := true;
             exit;
             end;

          audioCount := 0;
          x := frmMain.HbkStr.IndexOf('  + audio tracks:') + 1;
          repeat
                x := x + 1;
                AudioCount := AudioCount + 1;
                Synchronize(@prgUpdate);
          until (x = frmMain.HbkStr.Count - 1) or (x = frmMain.HbkStr.IndexOf('  + subtitle tracks:')) ;


          for x := 1 to AudioCount do begin
               Synchronize(@prgUpdate);
               audioTracks := audioTracks + intToStr(x);
               if x <> AudioCount then
                  audioTracks := audioTracks + ',';
          end;


          if frmMain.chkHardSubs.Checked = true then
          begin
                frmMain.lstOut.Items.add('HandbrakeCLI -i ' +  '"' + trim(frmMain.lstAdd.Items[frmMain.i]) + '" ' + ' -f mkv -o ' +  '"' + trim(frmMain.lstAdd.Items[frmMain.i]) + '-OUT.mkv' + '" '  + venString + trim(frmMain.txtVideoValue.Text) + ' -e x264 -x ' + x264String + ' -E vorbis -B '+ trim(frmMain.txtAudioValue.Text) + ' -w ' + trim(frmMain.txtWidth.Text) + ' -l ' + trim(frmMain.txtHeight.Text) + ' -s 1 --subtitle-burn 1' + ' -a ' + audioTracks);
          end
          else if frmMain.chkHardSubs.Checked = false then
          begin
                frmMain.lstOut.Items.add('HandbrakeCLI -i ' +  '"' + trim(frmMain.lstAdd.Items[frmMain.i]) + '" ' + ' -f mkv -o ' +  '"' + trim(frmMain.lstAdd.Items[frmMain.i]) + '-OUT.mkv' + '" '  + venString + trim(frmMain.txtVideoValue.Text) + ' -e x264 -x ' + x264String + ' -E vorbis -B '+ trim(frmMain.txtAudioValue.Text) + ' -w ' + trim(frmMain.txtWidth.Text) + ' -l ' + trim(frmMain.txtHeight.Text) + ' -a ' + audioTracks);
          end;

          Synchronize(@prgUpdate);
          scanned := true;
     end;

     if (scanned = true) and (frmMain.i < frmMain.lstAdd.Items.Count) and (sPro.Running = false) then
     begin
          //i := i + 1;
          Synchronize(@iUpdate);
          scanned := false;
          Synchronize(@prgUpdate);
     end;

     if (scanned = false) and (frmMain.i = frmMain.lstAdd.Items.Count)then
     begin
          //frmMain.tmrScan.Enabled := false;
          Synchronize(@prgUpdate);
          ShowMessage('Scanning Done');
          frmMain.btnEncode.Enabled := true;
          scanned := true;
          frmMain.prgScan.Position := frmMain.prgScan.Min;
          frmMain.lstAdd.Clear;
          frmMain.tbsOutput.Show;
          //sPro.Free;
          //M.Free;
     end;
end;                       

still no luck im getting that raised exception class 'EThread' with message: CheckSynchronize called from non-main thread

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TThread questions
« Reply #14 on: October 28, 2010, 05:02:58 pm »
As I said above, you cannot do things like:

frmMain.lstOut.Items.add

from the non-main-Thread.
It all has to go through Synchronize.
Or even better, let the thread to its job and work only with the returned data in the Form/MainThread

 

TinyPortal © 2005-2018