Jump to content
bravesofts

delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?

Recommended Posts

i have this code here:

fTask: ITask;

fTask := TTask.Create( procedure begin
  while not True do Application.ProcessMessages;
  TThread.Synchronize(TThread.Current, procedure begin
    // update ui
  end);
end);
fTask.ExecuteWork;  // this will stop here.. until [fTask] finish work !!

In android didn't wait untill Task Complete !!

Share this post


Link to post

I don't quite understand what you mean that it didn't wait until task complete, but you are using the task wrong.

 

First, you should never call ExecuteWork as it is internal method. You should use Start instead. Next code within task procedure will run in the background thread so when you call fTask.Start any code following that line will immediately run and it will not wait for task completion. The whole point of running a task is that it does not block further code along with the GUI.

 

Next, since task procedure will run in background thread, you must never call Application.ProcessMessages within, because it can only be called within main thread context. And because task is running in the background you don't need to manually pump message queue anyway. If you wanted to use it to simulate some work, just use some other code.

 

If you want to wait for task to complete you can call fTask.Wait, but this will then block the thread were it is called and if you call it on main thread it will block the main thread which defeats the purpose of running a task in the background. It only makes sense if user closes some form or similar and you need to wait for task to perform some cleanup. But in such scenarios you need to know that wait will be very short or you will get unresponsive application.

  • Like 1

Share this post


Link to post

This is my git repository uses that method executeWork:

Wait Solution Here

Maybe help to understand my request.. 

Nb: my repo not complete yet... 

Wait Solution (VCL/FMX) Stop the Use of Stupid Sleep function !!

Now with this Solution :

  1. your Main thread Should Wait until your wait function finsh her work without freezing the entire App using the stupid Sleep function !!!
  2. other Threads that are runing outside your MainThread (they still could work without Any Problem!!)
  3. using the method ExecuteWork from ITask we can force the App to wait until Our WaitThread finish work
Edited by bravesofts
Add NB

Share this post


Link to post

Is there any solution targeting the mobile devices!! 

----

I'm afraid that :

Delphi does not support background threads in Android and iOS devices !!

----

And if yes...  I think it's OS problem or Firemonkey single Main Activity doesn't accept more activities !!!
 

Edited by bravesofts
Typo

Share this post


Link to post

In android maybe android service could help... 

Or add some Java activities that play our background threads safely while our main thread App is using while loop application.processmessage;

Share this post


Link to post
2 hours ago, bravesofts said:

Maybe help to understand my request.. 

It doesn't help much. The code does not make sense, so it is very hard to understand what you want to accomplish and even more importantly why.

 

52 minutes ago, bravesofts said:

Is there any solution targeting the mobile devices!! 

----

I'm afraid that :

Delphi does not support background threads in Android and iOS devices !!

Delphi does support background threads on mobile devices, but again your code is very much wrong. 

 

Again, don't ever call ExecuteWork on task, use Start.

 

It would help if you could show your original code as in what you need to do, without your broken solution which just makes it harder to understand what you need.

  • Like 1

Share this post


Link to post
1 minute ago, bravesofts said:

In android maybe android service could help... 

Or add some Java activities that play our background threads safely while our main thread App is using while loop application.processmessage;

Do not call Application.ProcessMessages, it is a wrong solution to whatever problem you have.

  • Like 1

Share this post


Link to post
17 minutes ago, Dalija Prasnikar said:

It doesn't help much. The code does not make sense, so it is very hard to understand what you want to accomplish and even more importantly why.

 

Delphi does support background threads on mobile devices, but again your code is very much wrong. 

 

Again, don't ever call ExecuteWork on task, use Start.

 

It would help if you could show your original code as in what you need to do, without your broken solution which just makes it harder to understand what you need.

About my repository didn't help you understand my request... 

---

I simply if I Don't use itask.ExecuteWork; and use the regular  Start; 

The main thread App will not wait for task completion and execute the next line code... 

But with executeWork I succeeded to force main thread App to wait smoothly without freezing the app.... 

I don't like use sleep function inside while loop in order to execute background thread... 

---

Try to use my wrong code (like I said before it's not complete...) in VCL and FMX windows example and you will find the magic of executeWork method.. 

---

NB: sorry for my wrong solution in my GIthub.. 

Edited by bravesofts
Typo

Share this post


Link to post
11 minutes ago, bravesofts said:

I simply if I Don't use itask.ExecuteWork; and use the regular  Start; 

The main thread App will not wait for task completion and execute the next line code...   

This is why you are failing. The main thread should not wait for background thread to finish. If you need to run something after your task is completed you need to change your code logic and initiate that code from within TTask procedure. If you wait you will block the main thread and this is not something you should be doing, unless it is some very brief period for some cleanup (even then you need to be careful)

 

This is how you should use TTask to run task in background and then run some code after task finishes:

 

begin
  fTask := TTask.Create(
    procedure
    begin
      // Here you do your task code
      ...
      TThread.Synchronize(nil,
       procedure
       begin
         // Here you can call code that needs to run after task is finished
         ...
       end);
    end);
  fTask.Start;
end;

 

11 minutes ago, bravesofts said:

But with executeWork I succeeded to force main thread App to wait smoothly without freezing the app.... 

I don't like use sleep function inside while loop in order to execute background thread... 

If you change your code workflow, you will not need the Sleep or anything else.

11 minutes ago, bravesofts said:

Try to use my wrong code (like I said before it's not complete...) in VCL and FMX windows example and you will find the magic of executeWork method.. 

There is no magic there. Just because at some point it may look like it is doing what you want it to do, does not mean it is right way to do it. 

  • Like 1

Share this post


Link to post
48 minutes ago, Dalija Prasnikar said:

This is why you are failing. The main thread should not wait for background thread to finish. If you need to run something after your task is completed you need to change your code logic and initiate that code from within TTask procedure. If you wait you will block the main thread and this is not something you should be doing, unless it is some very brief period for some cleanup (even then you need to be careful)

 

This is how you should use TTask to run task in background and then run some code after task finishes:

 


begin
  fTask := TTask.Create(
    procedure
    begin
      // Here you do your task code
      ...
      TThread.Synchronize(nil,
       procedure
       begin
         // Here you can call code that needs to run after task is finished
         ...
       end);
    end);
  fTask.Start;
end;

 

If you change your code workflow, you will not need the Sleep or anything else.

There is no magic there. Just because at some point it may look like it is doing what you want it to do, does not mean it is right way to do it. 

Is there a safe solution to block the main thread smoothly without freezing the app while waiting our task to complete "using the right task way above.. " Especially in mobile devices

Edited by bravesofts

Share this post


Link to post
4 minutes ago, bravesofts said:

Is there a safe solution to block the main thread smoothly without freezing the app while waiting our task to complete "using the right task way above.. " Especially in mobile devices

On mobile devices you should never block the main thread (or risk that the OS will terminate your program).

 

Without more details we cannot help you. Most probably you want to disable the UI elements that are not allowed while your background thread is executing. 

  • Like 1

Share this post


Link to post
4 minutes ago, Lajos Juhász said:

On mobile devices you should never block the main thread (or risk that the OS will terminate your program).

 

Without more details we cannot help you. Most probably you want to disable the UI elements that are not allowed while your background thread is executing. 

Not block the main thread in that definition... !!!

I think the stupid sleep function is the unsafe way to block main thread... 

----

I mean block main thread using the safe way like executeWork does... 

----

I'm afread again :

Delphi does not support background threads in Android and iOS devices where the main thread wait smoothly and safe... 

Share this post


Link to post
6 minutes ago, bravesofts said:

I'm afread again :

Delphi does not support background threads in Android and iOS devices where the main thread wait smoothly and safe... 

 

On the other hand I believe you should learn a bit more about multi threading.

  • Like 1

Share this post


Link to post
20 minutes ago, bravesofts said:

Not block the main thread in that definition... !!!

I think the stupid sleep function is the unsafe way to block main thread... 

 

There is no safe way to block main thread. You should never, ever block main thread, especially not on mobile devices that have slightly different workflow than Windows. And yes, don't use Sleep either. The only proper solution for your problem is not to wait, reorganize code, so you don't have to wait.

Disable the UI to prevent user from starting something else while your task is running and enable the UI and run other code from within task procedure (synchronized) when the task is done.

20 minutes ago, bravesofts said:

I mean block main thread using the safe way like executeWork does... 

This is not a safe way. Your code is bad even on Windows, even though it seems like it works. This is the wrong way to deal with threads anywhere.

20 minutes ago, bravesofts said:

Delphi does not support background threads in Android and iOS devices where the main thread wait smoothly and safe... 

Again, it is not about Delphi, it is that this is the wrong way to use threads. 

  • Like 1

Share this post


Link to post

Make your app the OOP way and event driven, split your source into smaller parts, start your selfmade sleep and fire at sync an event that executes next things...

  • Confused 1

Share this post


Link to post
On 6/28/2023 at 12:15 PM, Dalija Prasnikar said:

There is no safe way to block main thread. You should never, ever block main thread, especially not on mobile devices that have slightly different workflow than Windows. And yes, don't use Sleep either. The only proper solution for your problem is not to wait, reorganize code, so you don't have to wait.

Disable the UI to prevent user from starting something else while your task is running and enable the UI and run other code from within task procedure (synchronized) when the task is done.

This is not a safe way. Your code is bad even on Windows, even though it seems like it works. This is the wrong way to deal with threads anywhere.

Again, it is not about Delphi, it is that this is the wrong way to use threads. 

sorry again ...

---

last question:

is it impossible to create threads in mobile devices while avoiding the main app thread from going to the next line of code until tasks complete ?
for example this code here didn't work in android devices:

begin
  _Taskcomplete := false;
  try
    fTask := TTask.Create(
      procedure
      begin
        // Here you do your task code
        while not _Taskcomplete do 
          Lbl_Task.Text := ElapsedSec.ToString;
        TThread.Synchronize(nil,
         procedure
         begin
           // Here you can call code that needs to run after task is finished
           Lbl_Task.Text := 'task complete ..';
         end);
      end);
    fTask.Start;
  finally
    while not _Taskcomplete do Application.ProcessMessage; // in Android the APP freeze !!
    showMessage('we wait until Task Complete to show you this message !!');
  end;   
end;

from what i learn above is i can only use wait function to run the SoCalled "After Task Complete Procedures or functions" inside the task thread using synchronize method..!!

Edited by bravesofts
complete writing

Share this post


Link to post
28 minutes ago, bravesofts said:

last question:

is it impossible to create threads in mobile devices while avoiding the main app thread from going to the next line of code until tasks complete ?

 

No. The reason to create a thread is to move to the next line without waiting for a block of code (inside the thread) to complete.  That's the purpose for threads in every platform.

 

  • Like 1

Share this post


Link to post
34 minutes ago, bravesofts said:

is it impossible to create threads in mobile devices while avoiding the main app thread from going to the next line of code until tasks complete ?

Yes, it is impossible. Also this approach while works on Windows is also not the best one. The only way to wait is using fTask.Wait, but then the main thread will block and OS will kill your application. If you need to run some code after task completes the only way to do that is from within task procedure.  Also if you start a task and then call wait you are defeating the purpose of having background thread in the first place.

 

begin
  _Taskcomplete := false;
    fTask := TTask.Create(
      procedure
      begin
        // Here you do your task code
        while not _Taskcomplete do 
          Lbl_Task.Text := ElapsedSec.ToString;
        TThread.Synchronize(nil,
         procedure
         begin
           // Here you can call code that needs to run after task is finished
           Lbl_Task.Text := 'task complete ..';
           showMessage('we wait until Task Complete to show you this message !!');
         end);
      end);
    fTask.Start;
end;

 

Edited by Dalija Prasnikar
  • Like 1

Share this post


Link to post
52 minutes ago, Dalija Prasnikar said:

Yes, it is impossible. Also this approach while works on Windows is also not the best one. The only way to wait is using fTask.Wait, but then the main thread will block and OS will kill your application. If you need to run some code after task completes the only way to do that is from within task procedure.  Also if you start a task and then call wait you are defeating the purpose of having background thread in the first place.

 

also i learn that the Method ExecuteWork: [ is used to run the task in the calling thread => in my case the main App thread ] like inject or run a safe thread inside the MainThreadAPP and this exactly what i looking for....
---
so my question here:
 Why 
Method ExecuteWork  Fail in mobile device (especially ANDROID) ?

-----

is this have problem with Android OS ??

-----

  Please don't tell me that Method : ExecuteWork is not a regular or illegal or what ever else ... otherwhise why the EMB Group add it inside the interface ITASK ?
----
what i know in language programming : the interface is safer and destinated at-least to users like me ....

---

with best Respects & Regards ...

 

Edited by bravesofts

Share this post


Link to post

 

sorry @Remy Lebeau no i didn't at that way !!

---

i ask both question at the same time !!

---

and with Your big and huge respect of your knowledge, I'm done learning that Method:

[ITask.ExecuteWork]

from ITask is:  runs the task in the calling thread ...
----

again please: Forgive my ignorance and stupidity !! i was just there to ask and not because this site or other didn't help !!

---

finally

. i thank you all for your replys and especially for taking from your time..

i love you all & respect you all ..

@Dalija Prasnikar regardless of others... i respect you a lot .

Share this post


Link to post
2 hours ago, bravesofts said:

 Why  Method ExecuteWork  Fail in mobile device (especially ANDROID) ?

Because there are differences between different operating systems and how their internals work. In other words, some things and some workflows that are possible on one operating system is impossible on another. 

2 hours ago, bravesofts said:

  Please don't tell me that Method : ExecuteWork is not a regular or illegal or what ever else ... otherwhise why the EMB Group add it inside the interface ITASK ?

Like I said before ExecuteWork is internal method and MUST NOT be used. It is part of the interface so internal code can call that method when appropriate, but this method is not part of public API. Forget that it exists. Just because some method is available and can be called does not mean it is meant to be used by developers, regardless of how it is available - through interface or directly through object instance. Another example of methods that should not be called directly is TThread.Execute, or TObject.FreeInstance... there are plenty of such examples around.

 

  • Like 3

Share this post


Link to post

Threads are about parallel/background work, but after invoking a task, you could in theory use ITask.Wait to stop the main thread while waiting for it to complete - but then you might as well execute the code from the main thread instead of creating other threads. Also, if the thread gets stuck, your main thread would be stuck. 

 

It is better to use parallel threads and in the main thread receive signal events for when the background thread succeeds/completes/fails. 

 

Threads are not hard when you understand them and the best practices around the use of them - but gaining that knowledge can be a challenge. 

Read the theory, study the examples, and try it out.

  • Like 2

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×