Recent

Author Topic: [SOLVED] Thread => AlwaysWaitForExecute ?  (Read 7502 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
[SOLVED] Thread => AlwaysWaitForExecute ?
« on: December 08, 2014, 01:47:40 pm »
Hello.

I have some trouble with thread   :-[

After execute the thread (who is perfectly running  :)), the main application stop to work, until the thread is terminated.

When the thread is terminated, the main application re-works perfectly.

That thread.execute is the main procedure of a graphical output library.

What to do to not stop the main process ?

Here part of the code

Code: [Select]
Type
   TPlugin = class(TThread)
  protected
    procedure Execute; override;
     public
  constructor Create(CreateSuspended: boolean;
      const StackSize: SizeUInt = DefaultStackSize);
end;

procedure TPlugin.execute;
  begin
  TheLibraryMainProc() ;
  end; 
What is wrong ?

Fred.

Thanks.
« Last Edit: January 05, 2015, 04:45:57 pm by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Thread => AlwaysWaitForExecute ?
« Reply #1 on: December 08, 2014, 06:17:02 pm »
depends on what TheLibraryMainProc does. Remember, no GUI update should be done by any thread but the main thread.

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #2 on: December 08, 2014, 07:46:02 pm »
Quote
no GUI update should be done by any thread but the main thread.

Hum, do you mean that a other thread may not do graphical things, even if those graphical things are not related to main thread ?

So i do not understand why a TProcess can do it and a TThread cannot.

Could it be possible to run that procedure of the library via a TProcess ?

Thanks.
« Last Edit: December 08, 2014, 07:52:07 pm by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: Thread => AlwaysWaitForExecute ?
« Reply #3 on: December 08, 2014, 10:03:51 pm »
Quote
no GUI update should be done by any thread but the main thread.

Hum, do you mean that a other thread may not do graphical things, even if those graphical things are not related to main thread ?

So i do not understand why a TProcess can do it and a TThread cannot.

Could it be possible to run that procedure of the library via a TProcess ?

Thanks.
Assumptions is the mother of all evil, you should know by now that you need to show us the code if you want us to find the problem.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Blestan

  • Sr. Member
  • ****
  • Posts: 461
Re: Thread => AlwaysWaitForExecute ?
« Reply #4 on: December 08, 2014, 10:11:07 pm »
Running a separate process cannot access your main form canvas - i.e updating the gui.
The main reason that only the main thread can update the gui is the event loop. Gui redraw is heavy based on messages passing - events. Lazarus apps are single event loop . Alll gui actions must be executed in the main thead via sync or something like that procedure. So if you lib is doing that you lose the advantage to execute it in a thread.
Speak postscript or die!
Translate to pdf and live!

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #5 on: December 09, 2014, 02:03:14 am »
Quote
show us the code

Ok, ok,...  :-[

Here the Program =>
Code: [Select]
program prog_graout;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils, Classes, fpg_base, fpg_main, fpg_form,
  h_graout;

type
  Ttest = class(TfpgForm)
  private
  public
    procedure AfterCreate; override;
  end;
 
 type
   TgraoutThread= class(TThread)
  protected
  procedure Execute; override;
    public
  constructor Create(CreateSuspended: boolean;
      const StackSize: SizeUInt = DefaultStackSize);
end;

var
 graoutThread : TgraoutThread;

constructor TgraoutThread.Create(CreateSuspended: boolean;
  const StackSize: SizeUInt);
  begin
   inherited Create(CreateSuspended, StackSize);
  FreeOnTerminate := true;
    end;
 
  procedure TgraoutThread.execute();
  begin
  graout_mainproc() ;
  end;

procedure Ttest.AfterCreate;
begin
  Name := 'test';
  SetPosition(459, 222, 300, 250);
  WindowTitle := 'I am the main program';
 end;

procedure MainProc;
var
  frm: Ttest;
  libpath : string;
  begin
    {$IFDEF Windows}
  libpath := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'graout.dll' ;
    {$else}
 
  libpath := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'libgraout.so' ;
   {$endif}
  fpgApplication.Initialize;
  try
  graout_loadlib(libpath) ; /// load library and create thread
 
  graoutthread := TgraoutThread.create(true); // create the thread
 
  graoutthread.execute ;    /// run main graphical procedure of library via thread.execute
 
  frm := Ttest.Create(nil);  // create main form
  fpgApplication.MainForm := frm;
  frm.Show;
  fpgApplication.Run;  // run main application
  finally

  graout_unloadlib() ;  // unload library

   frm.Free;
  end;
end;

begin
  MainProc;
end.

Here the Library =>
Code: [Select]
library graout;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils, Classes, fpg_base, fpg_main, fpg_form;

type
  TGraout = class(TfpgForm)
  private
   public
    procedure AfterCreate; override;
  end;
 
procedure TGraout.AfterCreate;
begin
  Name := 'graout';
  SetPosition(492, 285, 500, 250);
  WindowTitle := 'I am a graphic out library';
 end;


procedure graout_mainproc; cdecl;
var
  frm: TGraout;
begin
  fpgApplication.Initialize;
  try
    frm := TGraout.Create(nil);
    fpgApplication.MainForm := frm;
    frm.Show;
    fpgApplication.Run;
  finally
    frm.Free;
  end;
end;

exports
  graout_mainproc name 'graout_mainproc';

end.

And here the wrapper to the library =>
Code: [Select]
unit h_graout ;

interface

uses
  DynLibs;

var
  graout_mainproc : procedure(); cdecl;
 
 LibHandle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib
 ReferenceCounter : cardinal = 0;  // Reference counter
         
function graout_isLoaded() : boolean; inline;
function graout_loadlib(const libfilename: string): boolean; // load the lib
procedure graout_unloadlib(); // unload the lib

implementation

function graout_isloaded(): boolean;
begin
 Result := (LibHandle <> dynlibs.NilHandle);
end;

function graout_loadlib(const libfilename: string): boolean;
begin
   Result := False;
  if LibHandle<>0 then
begin
 Inc(ReferenceCounter);
result:=true
end  else begin
    if Length(libfilename) = 0 then exit;
    LibHandle:=DynLibs.LoadLibrary(libfilename);
  if LibHandle <> DynLibs.NilHandle then
       begin
    try
      Pointer(graout_mainproc) :=
        GetProcAddress(LibHandle, 'graout_mainproc');
       
    Result := graout_isLoaded;
    ReferenceCounter:=1;   
      except
      graout_unloadlib;
    end;
  end;
end;
end;

procedure graout_unloadlib();
begin
// < Reference counting
  if ReferenceCounter > 0 then
    dec(ReferenceCounter);
  if ReferenceCounter > 0 then
    exit;
  // >
  if LibHandle <> DynLibs.NilHandle then
  begin
    DynLibs.UnloadLibrary(LibHandle);
    LibHandle := DynLibs.NilHandle;
  end;
end;

end.

Fre;D
« Last Edit: December 10, 2014, 12:58:37 am by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Thread => AlwaysWaitForExecute ?
« Reply #6 on: December 09, 2014, 02:12:51 am »
Ok, ok,...  :-[
Now that's clear. Your library's thread function creates another fpGUI application & form instance, which has separate RTL from your app, but executes as a part of your app. I'm not quite sure about this behavior, it's more complex than just "GUI update from child thread" problem, but probably the same explanation applies.

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Thread => AlwaysWaitForExecute ?
« Reply #7 on: December 09, 2014, 02:58:03 am »
You're calling the execute function directly here
Code: [Select]
TestThread.execute(); /////// Here do not give te control back
I'm assuming you want to run it as a separate thread, so:
Code: [Select]
TestThread.start();

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #8 on: December 09, 2014, 04:00:54 pm »
Quote
I'm assuming you want to run it as a separate thread, so:

TestThread.start();

 =>

Quote
An unhandled exception occurred at $00007FAAFB7B0214:
EThread: CheckSynchronize called from non-main thread "$7FAAFB675700"
  $00007FAAFB7B0214
  $00007FAAFB7D2A08
  $00007FAAFB7D26EE
  $00007FAAFB7D7176
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Thread => AlwaysWaitForExecute ?
« Reply #9 on: December 09, 2014, 04:45:22 pm »
Who loaded the lib that contains the proc that you called in your test thread, the test thread itself or the main thread?

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Thread => AlwaysWaitForExecute ?
« Reply #10 on: December 09, 2014, 06:07:38 pm »
Well, i only tackled the most obvious mistake on start method. Second thing that is unknown to me is how Lazarus handles on the case here where there is 2 TApplications and 2 mainforms. According to those errors, not so well  :P

Just to clarify the calling order:
Code: [Select]
MainProc;
// ->
procedure MainProc;
var
  frm: Ttest;
begin
  fpgApplication.Initialize;
  try
    testloadlib('/home/fred/testgraphiclib/libtestgraphic.so') ;
    TestThread := TTestThread.Create(true) ;
    TestThread.start(); // Lets change it to start()
    frm := Ttest.Create(nil);
    fpgApplication.MainForm := frm;
    frm.Show;
    fpgApplication.Run;
    // Jump to program execution and threads, and resume here when application terminates
  finally
    frm.Free;
  end;
end;

procedure TTestThread.execute();
begin
  mainproctest();
  // -> jump to mainproctest, alias of a second mainproc
end;

procedure MainProc; cdecl;
var
  frm: Ttestlib;
begin
  fpgApplication.Initialize;
  try
    frm := Ttestlib.Create(nil);
    fpgApplication.MainForm := frm;
    frm.Show;
    fpgApplication.Run;
  finally
    frm.Free;
  end;
end;

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #11 on: December 09, 2014, 07:00:35 pm »
Quote
Who loaded the lib that contains the proc that you called in your test thread, the test thread itself or the main thread?

Quote
Just to clarify the calling order:

In example it is the main thread who =>

1) Load dynamically the library
2) Create the thread.
3) Do thread.execute => the thread.execute procedure is the main procedure exported in library.
4) Create his own form.

In attachment the great challenge of this winter
(need fpGUI package) =>

1) Compile (with -fPIC parameter) the library => graout.pas

2) Compile and Run progfpgui_graout.pas

All is permised => using TThread, TProcess, direct access, ...
And the Winner will be the one who can show the 2 forms working...

The Winner will get the Nobel Price of FPC too.

Fre:D


« Last Edit: December 10, 2014, 01:02:05 am by Fred vS »
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #12 on: December 23, 2014, 09:25:45 pm »
Quote
In attachment the great challenge of this winter
(need fpGUI package) =>

No Nobel Price this winter ?

(LCL and other widgets may challenge too  ;) )

Fred.

PS : Dont say "it is impossible" => Impossible is not a fpc word.
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Thread => AlwaysWaitForExecute ?
« Reply #13 on: December 25, 2014, 06:48:51 am »
Have you tried googling on "delphi form in dll"? Maybe it is what you are after, but alot has been already written about it.

Fred vS

  • Hero Member
  • *****
  • Posts: 1675
    • miXimum is the DJ's best friend
Re: Thread => AlwaysWaitForExecute ?
« Reply #14 on: January 05, 2015, 01:43:47 pm »
Quote
Have you tried googling on "delphi form in dll"?

Yep,  User137, many thanks to answer.

Hum, no i did not try this  :-X

Now it is done and , indeed, lot of things to find but all are taking about Modal forms (and that is not difficult to do).
The challenge is to have a "no-modal form in dll" and there... big silence...

But, step by step, i am sure that the challenge will be done...

Many thanks.
I use Lazarus 1.8.0 32/64 and FPC 3.0.3 32/64 on Linux Mint Mate 17 32/64, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs