Forum > Android-JVM

Android JNI Thread

(1/1)

tommy_rusev:
 :(There is one project for Android realized with Lazarus and android native controls (JNI).
I have a small problem with android native controls (JNI) all works perfectly until the time I had to use threads.
I notice that a problem arises when more than one thread (main thread and second thread) are executed simultaneously. For a long time I have tried to solve the problem but unsuccessfully.

Java side

--- Code: Java  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---class jThread extends Thread {    private boolean         mSynchronize = false;    private boolean         mPaused      = false;    private Object          mPauseLock   = null;    private int             PasObj       = 0;      // Pascal Obj    private Controls        controls     = null;   // Control Class for Event    public  boolean         mRun         = false;     public jThread(Controls ctrls, int pasobj)    {        PasObj   = pasobj;        controls = ctrls;        mPauseLock = new Object();    }     @Override    public void run()    {        mRun = true;        controls.jOnThread(PasObj, Const.Thread_Begin);        try {            controls.jOnThread(PasObj, Const.Thread_Execute);        } catch (Exception e) {            //String error = new String("Run: "+e.toString()+"\n");            //controls.ErrorLog.FileWrite(error.getBytes(),error.getBytes().length);        }        controls.jOnThread(PasObj, Const.Thread_End);        mRun = false;    }     public  void Synchronize(boolean sleep) {        mSynchronize = true;         new Handler(Looper.getMainLooper()).post(new Runnable() {            public void run() {                controls.jOnThread(PasObj, Const.Thread_Synchronize);                mSynchronize = false;            }        });         do {            try {                Thread.sleep(1);            } catch (InterruptedException e) {            }            if (!mSynchronize) {break;};        }        while (true);    }     public  void Resume() {        synchronized (mPauseLock) {            mPaused = false;            mPauseLock.notifyAll();        }    }     public  void Suspend() {        mPaused = true;        synchronized (mPauseLock) {            while (mPaused) {                try {                    mPauseLock.wait();                } catch (InterruptedException e) {                }            }        }    }     public  void Sleep(int Milliseconds) {        try {            Thread.sleep(Milliseconds);        } catch (InterruptedException e) {         }    }     public  void Free() {        mPauseLock = null;    }} 

Pascal and_function side

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Procedure Java_Event_pOnThread(env: PJNIEnv; this: jobject;                               Obj: TObject; Mode:Integer); cdecl;var fEnv : PJNIEnv; ID:pthread_t; I,Index:integer;begin if not (Assigned(Obj)) then Exit;  case TThreadMode(Mode) of  Thread_Begin:   begin    dbg('Java_Event_pOnThread begin');    Exit;   end;  Thread_End:   begin    dbg('Java_Event_pOnThread end');    Exit;   end;  Thread_Execute:   begin    dbg('Java_Event_pOnThread execute1');    if Obj is TThread then TThread(Obj).GenEvent_OnThread(TThreadMode(Mode));    dbg('Java_Event_pOnThread execute2');   end;  Thread_Synchronize:      begin    dbg('Java_Event_pOnThread synchronize1');    if Obj is TThread then TThread(Obj).GenEvent_OnThread(TThreadMode(Mode));    dbg('Java_Event_pOnThread synchronize2');   end; end;end; Function jGetMethodID(var Env : PJNIEnv; var jControls:jobject; FuncName, FuncSig : PChar) : jMethodID;var jClass : jobject;begin Result := nil; Env:=nil; gApp.jVM^.AttachCurrentThread(gApp.jVM,@Env,nil); if (Env = nil) then begin  dbgf(PChar(FuncName+' ('+IntToStr(gettid)+') Env = nil'));  Exit; end; dbg(Pchar(FuncName+'  ('+IntToStr(gettid)+')')); jClass := Env^.FindClass(Env,_cAppC); if (jClass = nil) then begin  dbge(PChar(FuncName+'  ('+IntToStr(gettid)+') jClass = nil'));  Exit; end; Result := Env^.GetMethodID(Env, jClass, FuncName, FuncSig); Env^.DeleteLocalRef(Env,jClass); jControls:=gApp.jControls;end;  //------------------------------------------------------------------------------// Thread//------------------------------------------------------------------------------Function jThread_Create(ClassObj : TObject) : jObject;Const _cFuncName = 'jThread_Create'; _cFuncSig  = '(ILjava/lang/String;)Ljava/lang/Object;';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := ClassObj; Result := Env^.CallObjectMethodA(Env,jControls,_jMethod,@_jParams); Result := Env^.NewGlobalRef(Env,Result); dbg(_cFuncName+' 2');end; Procedure jThread_Free(var Thread : jObject);Const _cFuncName = 'jThread_Free'; _cFuncSig  = '(Ljava/lang/Object;)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := Thread; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); Env^.DeleteGlobalRef(Env,Thread); Thread := nil; dbg(_cFuncName+' 2');end; Procedure jThread_Run(Thread : jObject);Const _cFuncName = 'jThread_Run'; _cFuncSig  = '(Ljava/lang/Object;)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := Thread; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); dbg(_cFuncName+' 2');end; Procedure jThread_Synchronize(Thread : jObject);Const _cFuncName = 'jThread_Synchronize'; _cFuncSig  = '(Ljava/lang/Object;)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig,s); _jParams[0].l := Thread; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); dbg(_cFuncName+' 2');end; Procedure jThread_Resume(Thread : jObject);Const _cFuncName = 'jThread_Resume'; _cFuncSig  = '(Ljava/lang/Object;)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := Thread; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); dbg(_cFuncName+' 2');end; Procedure jThread_Suspend(Thread : jObject);Const _cFuncName = 'jThread_Suspend'; _cFuncSig  = '(Ljava/lang/Object;)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..0] of jValue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := Thread; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); dbg(_cFuncName+' 2');end; Procedure jThread_Sleep(Thread : jObject; Milliseconds:integer);Const _cFuncName = 'jThread_Sleep'; _cFuncSig  = '(Ljava/lang/Object;I)V';Var Env : PJNIEnv; jControls: jobject; _jMethod : jMethodID {$IFDef FPC} = nil {$EndIf}; _jParams : Array[0..1] of jValue; PJ       : Pjvalue;begin if Thread = nil then Exit; _jMethod := jGetMethodID(Env,jControls,_cFuncName,_cFuncSig); _jParams[0].l := Thread; _jParams[1].i := Milliseconds; Env^.CallVoidMethodA(Env,jControls,_jMethod,@_jParams); dbg(PChar(_cFuncName+' 2 ('+IntToStr(Milliseconds)+')'));end; 
Pascal Thread class

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit osThread; interface uses  SysUtils,  And_Controls_Types, jni, And_Controls; { TThread } type TThreadMethod = procedure of object; TNotifyEvent = procedure(Sender: TObject) of object;  TThread = class private   FHandle: JObject;   FSuspended: Boolean;   FFinished: Boolean;   FRun: Boolean;   FMethod: TThreadMethod; protected   procedure Execute; virtual; abstract;   procedure Synchronize(Method: TThreadMethod); public   constructor Create(CreateSuspended: Boolean);   destructor Destroy; override;   procedure GenEvent_OnThread(Mode:TThreadMode);   procedure Sleep(Milliseconds:Longint);   procedure Resume;   procedure Suspend; end; implementation { TThread } constructor TThread.Create(CreateSuspended: Boolean);begin inherited Create; FSuspended:=CreateSuspended; FRun := not FSuspended; FHandle := jThread_Create(Self,ClassName); if FRun then jThread_Run(FHandle);end; destructor TThread.Destroy;begin if FHandle <> nil then jThread_Free(FHandle); FHandle:=nil; inherited Destroy;end; procedure TThread.GenEvent_OnThread(Mode: TThreadMode);begin case Mode of  Thread_Execute:Execute;  Thread_Synchronize:if Assigned(FMethod) then FMethod; end;end; procedure TThread.Sleep(Milliseconds: Longint);begin jThread_Sleep(FHandle,Milliseconds);end; procedure TThread.Resume;begin if not FSuspended then Exit; FSuspended := False; if not FRun then begin  FRun:=true;  jThread_Run(FHandle);  Exit; end; jThread_Resume(FHandle);end; procedure TThread.Suspend;begin if FSuspended or not FRun then Exit; FSuspended := True; if FRun then begin  jThread_Suspend(FHandle); end;end; procedure TThread.Synchronize(Method: TThreadMethod);begin if FSuspended or not FRun then Exit; FMethod := Method; fInitInfo := InitInfo; jThread_Synchronize(FHandle);end; end. 
pascal working thread

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit fuProcessThread; interface uses  SysUtils,  And_Controls_Types, jni, And_Controls,  osThread; type TProcessThread = class(TThread)private fText:String; procedure InternalTextSet;protected procedure Execute; override;public implementation procedure TProcessThread.InternalTextSet;begin .. change the text of the form (SetText) .. refresh form (invalidate) .. begins a long redraw process (around 10-15 milliseconds)end; procedure TProcessThread.Execute;begin jdbgf('--------->Execute start'); ..  .. ..working with a file or something else .. .. .. fText:='TEXT'; Synchronize(@InternalTextSet); .. .. ..continue working with a file or something else ..at this point the two threads are run together .. .. .. ..here somewhere gives a bug and the program stops ..differently once in the main thread elsewhere in the thread .. .. ----->    an error occurs only when both threads are executed. .. jdbgf('--------->Execute end');end; end. 

tommy_rusev:
If I use AsyncTask for a long time, there would be problems with memory leak on onPause, onResume, onConfigurationChanged events ?
Android then destroy and recreate activity and this is problem when using AsyncTask class or I'm mistaken ?

If I use the Service class, I will have the same problems as the Thread class ?

tommy_rusev:
I've solved the problem ...

When the static method Java_Event_pOnThread in Pascal side is called from a second thread and then from the main thread (the second thread does not complete the Java_Event_pOnThread method) has stack problems and JVM terminate the process.

tommy_rusev:
Also add to main unit of application and cthreads unit.

Navigation

[0] Message Index

Go to full version