[LAMW] TThread Synchronize and Queue not working lazarus / 43-Android ---------------------------------------------------------------------- WayneSherman · 2018-06-07 18:28 TThread is working to create and execute a thread, but TThread.Synchronize and TThread.Queue are not working. In Android/LAMW, from my secondary thread how can I cause the main GUI thread to execute a method or procedure? Does SendMessage / PostMessage work on Android? Thanks ---------------------------------------------------------------------- WayneSherman · 2018-06-12 02:40 Until we have a better way I used a JTimer as a work around.  The jTimer.OnTimer event runs in the context of the main thread.  I use it to poll a boolean variable that indicates the worker thread has some data waiting to update the GUI. A proper solution may require the Native_Activity input queue (see onInputQueueCreated) and possibly Looper. Some discussion is here:  http://www.ikerhurtado.com/android-ndk- native-activity-app-glue-lib-lifecycle-threads ---------------------------------------------------------------------- PascalDragon · 2018-06-15 13:17 I currently don't know the internals of LAMW, but for TThread.Synchronize() and TThread.Queue() to work the main thread needs to call CheckSynchronize(). ---------------------------------------------------------------------- wadman · 2018-06-15 13:33 Quote from: WayneSherman on June 07, 2018, 08:28:16 pmDoes SendMessage / PostMessage work on Android? Can u test my component TWCThread for android? http://forum.lazarus.freepascal.org/index.php/topic,34505.0.html https://github.com/wadman/wthread ---------------------------------------------------------------------- bmcsoft · 2020-12-06 13:40 Quote from: PascalDragon on June 15, 2018, 03:17:55 pmI currently don't know the internals of LAMW, but for TThread.Synchronize() and TThread.Queue() to work the main thread needs to call CheckSynchronize(). Yes, calling the CheckSynchronize from the main thread makes to handle the request (synchronize calls in the synchronize queue). But how to make it frequently? I want to make UDP-chat. Incoming messages received randomly and frequently. Do I need jTimer anyway? What a cumbersome decision! ---------------------------------------------------------------------- WayneSherman · 2020-12-06 16:22 Quote from: bmcsoft on December 06, 2020, 02:40:40 pm  Do I need jTimer anyway? What a cumbersome decision! I just looked at this again and found the java method "activity.runOnUiThread": https://stackoverflow.com/questions/13991952/messaging-to-ui-thread https://developer.android.com/reference/android/app/Activity#runOnUiTh read%28java.lang.Runnable%29 Currently, in the LAMW framework, runOnUiThread appears to only be used in one place (called from java): https://github.com/jmpessoa/lazandroidmodulewizard/blob/eb262aaec6cb6a bb9f5cedb9cd8e1f4a9205e208/android_wizard/smartdesigner/java/jBluetoot hClientSocket.java#L376 Code: Java  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i controls.activity.runOnUiThread(new Runnable() {        public void run() {                OnConnectResult();        };});  I found the Controls.activity java class defined here: https://github.com/jmpessoa/lazandroidmodulewizard/blob/9fb348aa181979 4c47cc464561ef93d287e92a1b/android_wizard/smartdesigner/java/Controls. java#L2179 I think the LAMW framework can be extended to make "runOnUiThread" available to pascal code.  But I don't know how to do it. ---------------------------------------------------------------------- jmpessoa · 2020-12-06 16:38 QuoteI think the LAMW framework can be extended to make "runOnUiThread" available to pascal code.  But I don't know how to do it. I will do it for you just now! ---------------------------------------------------------------------- WayneSherman · 2020-12-06 16:50 Thank you Jose.  Some background to previous message is here: https://stackoverflow.com/questions/13991952/messaging-to-ui-thread and here https://developer.android.com/guide/components/processes-and- threads.html#WorkerThreads There is also a way to post to the main UI message queue to run code in the main UI thread using the "View" java class (and its descendants): https://developer.android.com/reference/android/view/View#post(java.la ng.Runnable) https://developer.android.com/reference/android/view/View#postDelayed( java.lang.Runnable,%20long) The "post" and "postDelayed" methods are also used in the LAMW framework in a few places, but as far as I can tell, they are not exposed in a generic way for pascal code to use. ---------------------------------------------------------------------- jmpessoa · 2020-12-06 17:44 for the first suggestion: What about this warapper? Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         public void RunOnUiThread() {            controls.activity.runOnUiThread(new Runnable() {               public void run() {                  controls.pOnRunOnUiThread(PasObj);  //this wil call pascal in jForm  new event "OnRunOnUiThread"              };           });        }  Done! jForm: new method RunOnUiThread(); After Self.RunOnUiThread() You need handle the event property: "OnRunOnUiThread"  to put your code.... Can you test this solution? If need I can try some modification...... ---------------------------------------------------------------------- WayneSherman · 2020-12-06 21:17 Quote from: jmpessoa on December 06, 2020, 06:44:27 pmfor the first suggestion: What about this warapper? jForm: new method RunOnUiThread(); I think the API can be made more flexible and try to store less or no state in jform.  Also pass some reference / context data so when the method runs in a UI thread it has an object or index that can be used to reference the data it needs. Designing an API should not be done hastily, let me give this a little thought. ---------------------------------------------------------------------- WayneSherman · 2020-12-06 21:45 It would be nice to allow the API user to define their own methods in any class which get called  by the UI thread: 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 //LAMW Framework Code//android_bridges/androidwidget.pastype  TRunOnUIThreadMethod = procedure(const RefObject: TObject; const RefData: Integer) of Object;  //or if pointers are ok, then reference data can be passed in the pointer.  //TRunOnUIThreadMethod = procedure(const RefData: Pointer) of Object;      jForm = class(TAndroidForm)  public  ...    RunOnUiThread(const AMethod: TRunOnUIThreadMethod; const RefObject: TObject; const RefData: Integer);  ...      end; //User Code  TAndroidModule1 = class(jForm)  ...  end;   TSomeClass = class  ...    procedure RunThisMethodInTheUIThread(const RefObject: TObject; const RefData: Integer);  ...  end; var  AndroidModule1: TAndroidModule1;  SomeClass: TSomeClass; begin  AndroidModule1.RunOnUiThread(@SomeClass.RunThisMethodInTheUIThread, nil, 0); ---------------------------------------------------------------------- WayneSherman · 2020-12-06 22:43 Is jForm the appropriate class to implement RunOnUiThread? In java/android RunOnUiThread is a method of the Activity class, and in LAMW "activity" is a member of the Controls class (in Controls.java). So maybe jControl the right place to implement RunOnUiThread?: 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   jControl = class(TComponent)  public  ...    RunOnUiThread(const AMethod: TRunOnUIThreadMethod; const RefObject: TObject; const RefData: Integer);  ...      end;  In that case, any jcontrol can make use of it. ---------------------------------------------------------------------- jmpessoa · 2020-12-06 23:20 QuoteSo maybe jControl the right place to implement RunOnUiThread? Ok. I will try this solution, too... PS. Sorry... but  pascal "jControl"   and "Controls.java" don't have the same semantic....  "Controls.java" is where we define "jForm" class, too...  more important: all LAMW [java side] component have a reference to the "Controls"  instance of Controls.java The name ""Controls.java"" is a legacy code that refactored lost the original semantic [a container to all lamw controls....] today, each component has its own java class file... but ""Controls.java"" still is the main [JNI] java/pascal interface.  Maybe we can change it to  "Controller.java"  in some time.... ---------------------------------------------------------------------- jmpessoa · 2020-12-07 17:40 I just changed the jForm method signature to: RunOnUiThread(tag: integer) [changed method signature ...] Use: Self.RunOnUiThread(1) then, you need handle the event property: "OnRunOnUiThread"  to put your code... side note: Are you using LAMW "jUDPSocket" Component? [if yes,  can we improved it?] ---------------------------------------------------------------------- Segator · 2020-12-08 14:20 RunOnUiThread(i) is like an AsyncTask or a pascal thread?, i can execute io operations with out affect the UI? ---------------------------------------------------------------------- WayneSherman · 2020-12-08 16:07 Quote from: Segator on December 08, 2020, 03:20:27 pm  RunOnUiThread(i) is like an AsyncTask or a pascal thread?, i can execute io operations with out affect the UI? One use for RunOnUiThread(i) is to allow a background/worker thread to passed data to the UI.  A background thread should not call methods on UI controls directly since they were not designed to be thread safe.  For example, if a worker thread is used to receive data from an HTTP connection, and you want to display the information in the UI, the thread can call RunOnUiThread(i) to execute UI code which displays the data by calling methods on UI controls. https://developer.android.com/guide/components/processes-and-threads QuoteAdditionally, the Android UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:     Do not block the UI thread     Do not access the Android UI toolkit from outside the UI thread AsyncTask is a wrapper around a background/worker thread and callback which passes a result to the UI thread.  It can be used in a similar way: https://developer.android.com/reference/android/os/AsyncTask But according to the linked page, AsyncTask has bugs and has been deprecated "AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes. It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground, and does not provide much utility over using Executors directly." ---------------------------------------------------------------------- WayneSherman · 2020-12-08 16:18 Quote from: Segator on December 08, 2020, 03:20:27 pmRunOnUiThread(i) is like an AsyncTask or a pascal thread?, i can execute io operations with out affect the UI? Additionally, fpc threads (e.g. TThread) generally work as expected on Android to create and run code in separate threads, except TThread "synchronize" and "queue" methods do not work (they don't work with LAMW, but I don't know if this is a general problem with Android in fpc). ---------------------------------------------------------------------- Segator · 2020-12-10 18:22 QuoteBut according to the linked page, AsyncTask has bugs and has been deprecated So, is convenient change from AsyncTask to RunOnUiThread?