Jump to content

bravesofts

Members
  • Content Count

    37
  • Joined

  • Last visited

Posts posted by bravesofts


  1.  

    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 .


  2. 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 ...

     


  3. 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..!!


  4. 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... 


  5. 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


  6. 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.. 


  7. 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

  8. 26 minutes ago, FPiette said:

    A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance by calling the constructor. Class are handled "by reference".

     

    and what about the exe it's self ?

    does A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance inside the exe it's self and not comming from calling the constructor. !!!

    i mean the delphi is deployed for us a ready to use objects variables that pointer to the exe it's self (pre Allocated Classes)


  9. First : i have this code:

    type
      TClass_Instance = class(TClass_Ancestor)
    
      end;

    what happen at runtime when our program is using this Unit?

    i mean exactly this Explicit

    TClass_Instance = class(TClass_Ancestor)

    does this Allocate something in Memory ? or system resources ....

    second:

    ihave this declaration here:

    var
      vObj_Instance: TClass_Instance;
    begin
    
    end;

    what happen at runtime when we are declaring some Objects ?

    i mean exactly this Declaration 

    vObj_Instance: TClass_Instance;

    does this Allocate something in Memory ? or system resources ....

    third:

      i have this code here:

    type
      {$M+}
      TBaseForm = class(TForm) // This my template Base Form
        procedure Abstracted_Event(Sender: TObject); virtual; abstract;
      end;
    
      TSubBase_1 = class(TBaseForm)
        // SubBase_1 Members goes here ..
      published
        procedure Abstracted_Event(Sender: TObject); Override;  
      end;
    
      TSubBase_2 = class(TBaseForm)
      // SubBase_2 Members goes here ..
      published
        procedure Abstracted_Event(Sender: TObject); Override;
      end;
    
      TSubBase_3 = class(TBaseForm)
      // SubBase_3 Members goes here ..
      published
        procedure Abstracted_Event(Sender: TObject); Override;
      end;

    i have this super procedure for calling sub forms acording to their Class Names:

    procedure Get_SubForm(AFormClass: TFormClass; aOwner: TComponent; aParent: TWinControl);
    var
      vObjInstance: TBaseForm; // Define Object Instance Type;
      vRef: TBaseForm; // our Object vRef is the Universal variable for All SubForms that inherited from TBaseForm
    begin
      vObjInstance := TBaseForm(AFormClass.NewInstance); //Fill Object [vObjInstance] with [AFormClass.NewInstance] ..
      vRef         := vObjInstance.Create(aOwner); //Fill Object [vRef] with [vObjInstance.Create] ..
      try
        vRef.Parent      := aParent;
        vRef.Align       := alClient;
        vRef.BorderStyle := bsNone;
        vRef.OnShow      := vRef.Abstracted_Event;
      finally
        vRef.Show;
      end;
    end;
    Quote

      this code could be inside the baseform as global method or inside our MainForm Application

    my question is :

    what happen here:

     vObjInstance := TBaseForm(AFormClass.NewInstance); //Fill Object [vObjInstance] with [AFormClass.NewInstance] ..

    at runtime ...?

    does this line Above is trying to replace the first declaration Above here:

    var
      vObjInstance: TBaseForm; // Define Object Instance Type;

    in other words:

    does NewInstance Above is trying to redeclare our variable vObjInstance with Another Type ?

    if not (so what happen exactlly ?)

    Another sample Example:

    procedure TFrmMain.Btn_CreateObjClick(Sender: TObject);
    var
      vObj_Instance: TButton;  // declaration Type of our Object
      vRef: TButton;
    begin
      vObj_Instance := TButton(TButton.NewInstance);
    
      vRef          := vObj_Instance.Create(Self);
      try
        vRef.Parent := Self;
        vRef.Name   := 'Btn_vObj'+ ComponentCount.ToString;
        vRef.SetBounds(Round(8 * fScaleFactor), Round(48 * fScaleFactor), Round(185 * fScaleFactor), Round(41 * fScaleFactor));
    
      finally
        vRef.Visible := True;
      end;
    end;

    here i'm using the same approach Above that using TBaseForm but with one base Class TButton

    my question is:

    we used to use this Rule here:

    <vObject> := <ClassName>.<ConstructorName> ;

    but here we have an object trying to Allocate the memory (fiil the Class inside that variable) for Another Object ...

    my Remark:

    procedure TFrmMain.Btn_CreateObjClick(Sender: TObject);
    var
    //  vObj_Instance: TButton; 
      vRef: TButton;
    begin
    //  vObj_Instance := TButton(TButton.NewInstance);
    
      vRef          := Btn_CreateObj.Create(Self);
      try
        vRef.Parent := Self;
        vRef.Name   := 'Btn_vObj'+ ComponentCount.ToString;
        vRef.SetBounds(Round(8 * fScaleFactor), Round(48 * fScaleFactor), Round(185 * fScaleFactor), Round(41 * fScaleFactor));
    
      finally
        vRef.Visible := True;
      end;
    end;

    if we click on button Btn_CreateObj  the object will be created but the Button Btn_CreateObj will be disappear !!! and when closing the app will have a memory leaks !!!

    my Approach of using another variable as a mediator, remind me with A & B replacement values

    var
      A, B, C: integer;
    begin
      A := 10; B := 5;
    
     // Solving requiring us Another Variable with the same Type
      C := A;
      A := B; 
      B := C; // AND IT'S DONE ..
       
    end;

    finally:

      what is a Class Instance and an Object Instance?

      and is my Approach for creating base forms is a good approach or not ?

    thanks in Advance...


  10. i have another Kinda strange question: (Maybe a Stupid hhh :) ) 

    why the components that we create at designtime can call them using their NAME's Rather Call them from their Variables Names that Contains them  ?

    in runtime we can do this for ex:

    procedure CreateButton(aParent: TWinControl; aBtnEvent: TNotifyEvent);
    var
      vButton: TButton;
    begin
      vButton := TButton.Create(Self);
      try
        vButton.Parent := aParent; 
        vButton.Name := 'Btn_Test';
        vButton.SetBounds(10, 10, 100, 25);
        vButton.Caption := 'Test';
        vButton.OnClick := aBtnEvent;
      finally
        vButton.Visible := True;
      end;
    end;

    whereas any Object created at designtime we call them using their Name !!!

    --------

    what is the secret thing or the missing part that should i know (seriously) to understand the difference between an Object Name at DesignTime & Obj Name RunTime ?

    --------

    i know Logically that we can't Call any Obj not yet created in designtime from his NAME because it is not reconized for our Project yet (Therefore, we used variables instead), whereas we can call Objects that was created at designTime just from their Names because our Project know them & Recognize them !!(so how did recognize them and use TComponentName which is a string by default as pointer or i don't know as whatever is !!!)

    -------

    what i mean exactlly:

    what happen to any OBJ CREATED AT DESIGNTIME makes delphi & our project call them from thier Names instead of variables Names like the RunTime Scenario does ??

    --------

    i know that my question is trivial & stupid !!!

    but (seriously) i'm lost here (i know that i missing An essential thing that childrens know ....) 

    plz clarify to me the Secret behind delphi backstage designtime objects !!!

    Notice: All Objects will at the end created Atruntime (so why designtime is a superbox than others !!! (is a designtime = a temporary or pre runtime section or what is the word that can describe this superbox better than designtime ???) )

    --------

    in another meaning:

    why TComponentName of any OBJECT from ObjectInspector IS totally different from TComponentName of Runtime of any Object !!!

    they are both a string (TComponentName = type string;) from System.Classes

    --------

    thanks in advance

     


  11. Quote
    
    fBASE.Name := 'My Name'; // give fBASE a name

    is it fBase the name of that Object fBase ? and fConcrete the name of fConcrete Object

    --------

    for example the NORMAL Button when user click on it it will give him the TButton as ClassName and the 

    Btn_Normal_Event

    as Object Name where the Default was Button1 in Delphi

     


  12. i have this Abstract Base Unit :

    unit UBase;
    
    interface
    
    uses
      System.Classes;
    
    type
      TBaseAbstract = class(TComponent) 
        procedure Method(aObjectEvent: TNotifyEvent); virtual; abstract; 
      end;
    
      TConcrete = class(TBaseAbstract)
        procedure Method(aObjectEvent: TNotifyEvent); override; 
      strict private
        fReadOnlyProperty: string;
      public
        constructor New(aValue: string; aOwner: TComponent);
        destructor Destroy; override;
        property ReadOnlyProperty: string Read fReadOnlyProperty; // Read Only Property ..
      end;
    
    
    implementation
    
    { TConcrete }
    
    destructor TConcrete.Destroy;
    begin
    
      inherited;
    end;
    
    procedure TConcrete.Method(aObjectEvent: TNotifyEvent);
    begin
      aObjectEvent(Self)
    end;
    
    constructor TConcrete.New(aValue: string; aOwner: TComponent);
    begin
      inherited Create(aOwner);
    
      fReadOnlyProperty := aValue + Self.ClassName +' ] '+ sLineBreak +
                          'Object Instance Name is: [' + Self.Name +' ]';
    end;
    
    end.
    Quote

      in this Unit i'm using TCOMPONENT ANCESTOR for Abstracted Base Class in-order to get TComponentName for the Object that will Instantiate from TBaseAbstract Class

    in my App Demo Main Form i have this:

    var
      FrmMain: TFrmMain;
    
    implementation
    
    uses
      UBase;
    
    var
      fConcrete: TConcrete;
      fBASE: TBaseAbstract; 
    
    {$R *.dfm}
    
    procedure TFrmMain.FormCreate(Sender: TObject);
    begin
      fConcrete := TConcrete.New('i''m a Read Only PROPERTY of [ ', Self);
    end;
    
    procedure TFrmMain.FormDestroy(Sender: TObject);
    begin
      fConcrete.Free;
    end;
    
    procedure TFrmMain.Btn_Normal_EventClick(Sender: TObject);
    begin
      ShowMessage('i''m an Event of [ ' + Sender.ClassName +' ] '+ sLineBreak +
                  ' And My Object Instance Name IS: [ ' + TComponent(Sender).Name +' ]');
    end;
    
    procedure TFrmMain.Btn_Call_MethodClick(Sender: TObject);
    begin
      fBASE := TConcrete.Create(nil);
      try
        fBASE.Method(Btn_Normal_Event.OnClick);
      finally
        fBASE.Free;
      end;
    end;
    
    procedure TFrmMain.Btn_Call_Abstract_MethodClick(Sender: TObject);
    begin
      fConcrete.Method(Btn_Normal_Event.OnClick);
    end;
    
    procedure TFrmMain.Btn_Get_Concret_PropertyClick(Sender: TObject);
    begin
      ShowMessage(fConcrete.ReadOnlyProperty);
    end;
    
    end.

    Btn_Normal_EventClick work correctlly (i got the name of this button when i click on it [Btn_Normal_Event])

    but from fConcrete or fBase whether using Abstract Method or GetProperty the NAME IS EMPTY !!!

    ------------

    do i missing something ?


  13. 15 hours ago, shineworld said:

    Any idea on how to "force" the scrollbar colors?
    With dark mode are very very ugly:
    image.thumb.png.c5166c7dc2bdbc9d527dff5ae41c3f3a.png

    I've googled a lot searching for a way to use TThemeManager forcing it only to a component without results...

    try to add TScrollbar and make it related with that SynEdit and finally you will have a completely separated scrollbar with StyleElement property

    don't forget to make Scrollbars property to ssNone for your SynEdit


  14. 18 minutes ago, Lars Fosdal said:

    Avoid using short strings. Short string is for backwards compatibility only (typically for older desktop apps migrated to the new).

    They are ANSI based and do not support Unicode natively, and have been deprecated since 2009 when the Unicode string format was made king of the hill.

     

    Byte still is a useful number format when you don't need a large range, 

    Thank you so much ...


  15. i read carefully this Emb docwiki page here

    And this sentence caught my eye:

    Note: ShortString is used by the Delphi desktop compilers, but is not supported by the Delphi mobile compilers. For more information, see Migrating Delphi Code to Mobile from Desktop.

    does this mean a desktop program is compatible to work with this shortstring without any future problems while in mobile can't ...?

    or shortstring is not compatible for any platform (is just  maintained for backward compatibility only. like coding a library for example ...)

    -----

    Also :

    if my first understanding is true, why there is no shortstring in mobile platforms (I think the mobile platforms is the first and most deserving of this Short TYPE HAhA HAhA HAhA )

    Also:

    why Shortstring is Old and eliminated or Died while Byte Still Alive...

    -------------

    Note: My question is Related with this Question here.


  16. 11 minutes ago, David Heffernan said:

    No there is not.

     

    However, you really should not be using short strings at all. These only exist for backwards compatibility with legacy code.

    It seems to me that this technique is not implemented yet !! (not only delphi maybe all languages)

    ---------

    and thank you All for the Advice about the shortstring ...

×