LAMW and TThread lazarus / 43-Android ---------------------------------------------------------------------- Robert Gilland · 2019-06-14 02:27 The below code crashes my app, id dies when it calls the line "inherited Create(TRUE)", any Ideas? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TTestThread = class(TThread)     procedure Execute;  override;     constructor Create;   end;  constructor TTestThread.Create;begin  inherited Create(TRUE);  FreeOnTerminate := TRUE;end; procedure TTestThread.Execute;begin end; procedure TAndroidModule2.TestThreading;begin  TTestThread.Create;end; ---------------------------------------------------------------------- SymbolicFrank · 2019-06-14 06:07 Do you call the Create of the instance, instead of the type? ---------------------------------------------------------------------- PascalDragon · 2019-06-14 07:06 Does your main project file have the cthreads unit in its usage clause? This unit is required on *nix systems which Android is one of. The Lazarus templates usually have the unit protected by a {$ifdef unix}{$ifdef usecthreads}cthreads{$endif}{$endif} or so, so you need to define the usecthreads define in that case (or remove the ifdef altogether). ---------------------------------------------------------------------- Robert Gilland · 2019-06-15 23:50 Thank you PascalDragon, "cThreads" did stop the app crash. However now I can't get the OnTerminate event to be called see below code. When run the jProgressDialog does not close. Any Ideas? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TTestThread = class(TThread)     procedure Execute;  override;     constructor Create( pOnTerminateEvent : TNotifyEvent);   end;      TAndroidModule1 = class(jForm)        dlgTestProgress: jDialogProgress;       thrdSendOffLine : TTestThread;         end;      procedure TAndroidModule1.TestTerminated(Sender: TObject);begin  dlgTestProgress.Close;end; constructor TTestThread.Create( pOnTerminateEvent : TNotifyEvent);begin inherited Create(TRUE); OnTerminate := pOnTerminateEvent; FreeOnTerminate := TRUE;end;  procedure TTestThread.Execute;begin end;  procedure TAndroidModule1.RunThreadTest;begin  dlgTestProgress.Show();  thrdSendOffLine  := TTestThread.Create(TestTerminated);  thrdSendOffLine.Start;end; ---------------------------------------------------------------------- PascalDragon · 2019-06-22 15:53 It could be that the main thread is not calling CheckSynchronize as OnTerminate is called using Synchronize. I don't have enough experience with Android modules in FPC, so I don't know whether there is supposed to be component that's indeed calling that function or not. ---------------------------------------------------------------------- engkin · 2019-06-22 17:24 IIRC, your code in LAMW resides in a library (.so). Probably the best option for you to get TThread to work as you expect is to fake a main thread like in this case. ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 03:38 I have looked at https://forum.lazarus.freepascal.org/index.php/topic,44522.0.html. This looks rather not usable inside the LAMW framework, unless I am mistaken. LAMW creates a libcontrols.so library, then does a lot of packaging to make an Androd App. I will keep looking though ---------------------------------------------------------------------- jmpessoa · 2019-06-24 04:13 QuoteThis looks rather not usable inside the LAMW framework, unless I am mistaken.... I think you could give it a try ... LAMW lib/.so  is a "TCustomApplication",  too... What is going to be precessed in the TThread? ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 04:49 The application simply makes web service calls in response to the users interactions, some of these web service calls may take some time. I want a thread to process the web service call. allowing the main app to show a progress dialog until the web service API returns. This is proving far more difficult than I hoped for. I still have not worked out how the packaging of the app works, so I don't know how to add a separate library beside as this solution states can be done. ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 04:54 I am wondering if there could not be a "jThread" component to make threads inside LAMW applications? ---------------------------------------------------------------------- jmpessoa · 2019-06-24 04:58 Quote so I don't know how to add a separate library beside as this solution states can be done.... Put your custom ".so"  [can be a simple raw ".so" ] in the same folder as  "libcontrols.so" ....  LAMW will takes care of your library automatically... QuoteI am wondering if there could not be a "jThread" component to make threads inside LAMW applications? jHttpClient component has some "async" methods.....  what you need? ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 05:13 will give AppAsyncTaskDemo1 a try it does look promising ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 05:56 If I could make a "WST" ( web services toolkit ) transport based on jHttpClient async methods , then we just might have a viable solution. ---------------------------------------------------------------------- Robert Gilland · 2019-06-24 06:59 We have a winner "jAsyncTask"can handle the requirement ---------------------------------------------------------------------- jmpessoa · 2019-06-24 17:40 QuoteWe have a winner "jAsyncTask"can handle the requirement Nice! What about a simple demo  jAsyncTask +  WST? You can help all LAMW/Lazarus/FreePascal  community!!! ---------------------------------------------------------------------- Robert Gilland · 2019-06-25 06:53 here is the core code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {Hint: save all files to location: C:\adt32\eclipse\workspace\asyncdemo\jni }unit unit1;  {$mode delphi}  interface  uses  Classes, SysUtils, Laz_And_Controls, AndroidWidget, user_service_intf,  user_service_intf_proxy, And_Log_h;  type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)      jAsyncTask1: jAsyncTask;      jButton1: jButton;      jDialogProgress1: jDialogProgress;      jEditText1: jEditText;      jListView1: jListView;      procedure AndroidModule1Create(Sender: TObject);      procedure AndroidModule1Destroy(Sender: TObject);      procedure jAsyncTask1DoInBackground(Sender: TObject; progress: Integer;        out keepInBackground: boolean);      procedure jAsyncTask1PostExecute(Sender: TObject; progress: integer);      procedure jAsyncTask1PreExecute(Sender: TObject; out        startProgress: integer);      procedure jButton1Click(Sender: TObject);    private      {private declarations}      procedure LogMessage( psMsg : String );      procedure   RunGetUsers;      function CreateUserProxy : UserService;    public      {public declarations}      slUsers : TStringList;  end; var  AndroidModule1: TAndroidModule1; implementation  {$R *.lfm} uses soap_formatter, json_formatter, xmlrpc_formatter, fpc_http_protocol, service_intf; { TAndroidModule1 }  procedure TAndroidModule1.jAsyncTask1DoInBackground(Sender: TObject; progress: Integer; out keepInBackground: boolean);begin  RunGetUsers;  keepInBackground:= False;end; procedure TAndroidModule1.AndroidModule1Create(Sender: TObject);begin  slUsers := tStringList.Create;end; procedure TAndroidModule1.AndroidModule1Destroy(Sender: TObject);begin  slUsers.Free;end; procedure TAndroidModule1.jAsyncTask1PostExecute(Sender: TObject; progress: integer);begin  LogMessage('Dialog Stop');  jDialogProgress1.Stop;  LogMessage('Async Stop');  jAsyncTask1.Done;  LogMessage('List View Assign');  jListView1.Items.Assign(slUsers);  ShowMessage(slUsers.text);end; procedure TAndroidModule1.jAsyncTask1PreExecute(Sender: TObject; out startProgress: integer);begin   startProgress:= 0;  //out param !   LogMessage('Dialog Start');   jDialogProgress1.Start; //or Showend;    procedure TAndroidModule1.jButton1Click(Sender: TObject);begin    if not jAsyncTask1.Running then   begin     //ShowMessage('Execute ... ');     jAsyncTask1.Execute   end  else   ShowMessage('Running...');end; procedure TAndroidModule1.LogMessage(psMsg: String);begin  __android_log_write(A NDROID_LOG_INFO,PChar(Text),PChar(psMsg));end; procedure TAndroidModule1.RunGetUsers;var  lpUserService : UserService;  loUserArray   : TUserArray;  loUser        : TUser;  i             : Integer; begin  LogMessage('Create proxy');  lpUserService := CreateUserProxy;  LogMessage('proxy Get List');  loUserArray   := lpUserService.GetList();  slUsers.Clear;  LogMessage('List Length ' + IntToStr(loUserArray.Length));  for i := 0 to loUserArray.Length-1 do    begin      loUser := loUserArray[i];      slUsers.Add( loUser.UserName );    end;end; function TAndroidModule1.CreateUserProxy: UserService;var  buffsimplecall, buffTransport, buffFormat : string;   function GetServiceURL( WebServiceAddress : String ):String;  begin    Result := WebServiceAddress   + '/services/UserService';  end; begin  buffFormat     := 'json';  buffsimplecall := 'http:Address=' + GetServiceURL(jEditText1.Text) + '/?format=' + buffFormat;  buffTransport  := buffsimplecall;  buffFormat := buffFormat + ':';  LogMessage(buffTransport);  LogMessage(buffFormat);  Result     := TUserService_Proxy.Create( 'UserService',  buffFormat,  buffTransport  );end;  end. ---------------------------------------------------------------------- bmcsoft · 2020-12-06 09:47 When I create TThread in LAMW, I've got black screen on my phone. I can't see main form with jButton and jEditText. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i MyThread = class(TThread)private protected  procedure Execute; override;end; ... procedure TAndroidModule1.AndroidModule1Create(Sender: TObject);begin    sock:=TUDPBlockSocket.Create;     ThreadBegin := MyThread.Create (false); // ThreadBegin := MyThread.Create (true) - don't work also  ThreadBegin.FreeOnTerminate := true;    ThreadBegin.Priority:=tpNormal;end; procedure MyThread.Execute;var  buf: string;begin    sock.Bind('0.0.0.0','15001');    if sock.LastError<>0 then exit;    while True do      begin      if terminated then break;      buf := sock.RecvPacket(1000);      if sock.lasterror=0 then        begin        le2:=sock.GetRemoteSinIP;      le3:=IntToStr (sock.GetRemoteSinPort);        AndroidModule1.jEditText1.Text:=buf;        end;      sleep(1);      end;end; When I remove "ThreadBegin := MyThread.Create (false)" string, app starts normally and main form shows jButton and jEditText. Help me please, I'm novice in Android and LAMW. Such code in Windows works normally with TThread. ---------------------------------------------------------------------- bmcsoft · 2020-12-06 11:51 I found the information about it: "You don´t need any special unit for this to work with Windows. However with Linux, macOS and FreeBSD, you need the cthreads unit and it must be the first used unit of the project (the program source, usually the .lpr file)!". Key words here is: "first used unit of the project is lpr-file". When I edit Unit1.pas with "use cthreads" it did not work! ---------------------------------------------------------------------- jmpessoa · 2020-12-06 20:18 @bmcsoft QuoteKey words here is: "first used unit of the project is lpr-file". When I edit Unit1.pas with "use cthreads" it did not work! So you are suggesting changing these lines of code from Unit*.pas to "controls.lpr" ?? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}   If yes, I can do that! ---------------------------------------------------------------------- lucamar · 2020-12-06 23:39 Quote from: jmpessoa on December 06, 2020, 09:18:57 pmSo you are suggesting changing these lines of code from Unit*.pas to "controls.lpr" ?? [...snip ...] Yes; as happens with the alternative C memory manager (cmem), if used at all those units must be the very first in the uses clause of the program itself (the "lpr", in Lazarus parlance) because they need to be initialized (and the dynamic lib loaded, if needed) for any other code to be aware of it when needed, say, in the initialization of the RTL/FCL/LCL, etc.