As I said above, you cannot do things like:frmMain.lstOut.Items.addfrom 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
thanks a lot man and for the rest of the lazarus community on patiently guiding me i managed to finished it now and its working good
procedure TMyThread.Execute;repeat if (scanned = false) and (i < frmMain.lstAdd.Items.Count) then begin sPro.CommandLine := 'HandbrakeCLI -i ' + '"' + frmMain.lstAdd.Items[i] + '"' + ' -t 0';
But don't say I didn't warn you! ;-)Such hazardous thread code may work ten or a thousand times, but it will fail sooner or later giving really nasty and "unexplainable" results.
procedure TMyThread.Execute;const READ_BYTES = 2048;beginrepeat if (scanned = false) and (i < strScan.Items.Count) then begin Synchronize(@ScanStats); sPro.CommandLine := 'HandbrakeCLI -i ' + '"' + strScan.Items[i] + '"' + ' -t 0'; sPro.Options := [poUsePipes, poStderrToOutPut]; sPro.ShowWindow := swoHide; 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); Synchronize(@ScanOut); end; if (scanned = true) and (i < strScan.Items.Count) then begin Synchronize(@ScanInc); end; if (scanned = false) and (i = strScan.Items.Count)then begin Synchronize(@ScanDone); end;until i = strScan.Items.Count;end;
TMyThread = class(TThread) private audioCount: integer; venString: string; x264String: string; sPro: TProcess; M: TmemoryStream; n: longInt; BytesRead: longInt; strScan: TListBox; procedure ScanOut; procedure ScanInc; procedure ScanDone; procedure ScanStats; procedure prgUpdate; protected procedure Execute; override; public Constructor Create(CreateSuspended : boolean); end;
scanThread.strScan := lstAdd;
i created a variable on TMyThread called strScan as TListBox the code on execute method looks like this now (no more frmMain references on execute method area)
Quote from: ios on October 30, 2010, 01:37:03 ami created a variable on TMyThread called strScan as TListBox the code on execute method looks like this now (no more frmMain references on execute method area)Sorry, not GUI Code in threads, so no TListBox. But you can use TStringList.It's better to look at the Thread like a console program.Give some input -> Execute -> read the output.I already told you this:"Or even better, let the thread do its job and work only with the returned data in the Form/MainThread"Once you have no more GUI/Mainform/Mainthread Stuff in your code, and read the output in the OnTerminate event handler. you can start using a single "Synchronize" if absolutely necessary.Don't try to be smart, write just very simple and clean code.
procedure TMyThread.Execute;const READ_BYTES = 2048;beginrepeat Synchronize(@ScanStats); sPro.CommandLine := 'HandbrakeCLI -i ' + '"' + strScan[ii] + '"' + ' -t 0'; sPro.Options := [poUsePipes, poStderrToOutPut]; sPro.ShowWindow := swoHide; 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); Synchronize(@ScanOut); ii := ii + 1;until ii = strScan.Count;end;