bravesofts 6 Posted June 28, 2023 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
Dalija Prasnikar 1396 Posted June 28, 2023 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. 1 Share this post Link to post
bravesofts 6 Posted June 28, 2023 (edited) 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 : your Main thread Should Wait until your wait function finsh her work without freezing the entire App using the stupid Sleep function !!! other Threads that are runing outside your MainThread (they still could work without Any Problem!!) using the method ExecuteWork from ITask we can force the App to wait until Our WaitThread finish work Edited June 28, 2023 by bravesofts Add NB Share this post Link to post
bravesofts 6 Posted June 28, 2023 (edited) 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 June 28, 2023 by bravesofts Typo Share this post Link to post
Lajos Juhász 293 Posted June 28, 2023 19 minutes ago, bravesofts said: Delphi does not support background threads in Android and iOS devices !! https://blog.marcocantu.com/blog/2014_may_background_delphi_android_threads.html Share this post Link to post
bravesofts 6 Posted June 28, 2023 29 minutes ago, Lajos Juhász said: https://blog.marcocantu.com/blog/2014_may_background_delphi_android_threads.html Unfortunately didn't help at all... I see that post before.. Share this post Link to post
bravesofts 6 Posted June 28, 2023 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
Dalija Prasnikar 1396 Posted June 28, 2023 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. 1 Share this post Link to post
Dalija Prasnikar 1396 Posted June 28, 2023 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. 1 Share this post Link to post
bravesofts 6 Posted June 28, 2023 (edited) 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 June 28, 2023 by bravesofts Typo Share this post Link to post
Dalija Prasnikar 1396 Posted June 28, 2023 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. 1 Share this post Link to post
bravesofts 6 Posted June 28, 2023 (edited) 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 June 28, 2023 by bravesofts Share this post Link to post
Lajos Juhász 293 Posted June 28, 2023 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. 1 Share this post Link to post
bravesofts 6 Posted June 28, 2023 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
Lajos Juhász 293 Posted June 28, 2023 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. 1 Share this post Link to post
Dalija Prasnikar 1396 Posted June 28, 2023 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. 1 Share this post Link to post
KodeZwerg 54 Posted June 28, 2023 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... 1 Share this post Link to post
bravesofts 6 Posted June 29, 2023 (edited) 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 June 29, 2023 by bravesofts complete writing Share this post Link to post
Lajos Juhász 293 Posted June 29, 2023 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. 1 Share this post Link to post
Dalija Prasnikar 1396 Posted June 29, 2023 (edited) 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 June 29, 2023 by Dalija Prasnikar 1 Share this post Link to post
bravesofts 6 Posted June 29, 2023 (edited) 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 June 29, 2023 by bravesofts Share this post Link to post
Remy Lebeau 1396 Posted June 29, 2023 @bravesofts This was already covered on your StackOverflow question yesterday: delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices? Guess you didn't like what you were told there? So you came here instead, just to be told the same things. Funny how the same knowledge can span across multiple forums, huh? 😉 1 Share this post Link to post
bravesofts 6 Posted June 29, 2023 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
Dalija Prasnikar 1396 Posted June 29, 2023 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. 3 Share this post Link to post
Lars Fosdal 1792 Posted June 30, 2023 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. 2 Share this post Link to post