Hello

Hello,

I was looking at the Task example at the EMB wiki link below

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Tutorial:_Using_Tasks_from_the_Parallel_Programming_Library

and I don't understand the following part of the second Delphi example:

TThread.Synchronize(nil,
procedure
begin
Label1.Text := lValue.ToString;
end);

why is there the need to pass Label1.Text := lValue.ToString; as procedure in TThread.Synchronize ? Why not a simple Label1.Text := lValue.ToString; ?
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Tutorial:_Using_Tasks_from_the_Parallel_Programming_Library

Comments

  1. Lars Fosdal so, the big plus for the threads queues is they allow to customise the way the GUI is updated, for instance by updating the GUI based on the result of multiple tasks all at once. This is possible because the procedure that updates the GUI is customised too.
    On the other side, by using Synchronize, the GUI update is performed based on one task result at the time and this may have an impact on the performance.

    It is all about performance, am I correct ?

    ReplyDelete
  2. Performance and control. UI changes often have side effects (OnChange, etc). I prefer to be in control of when those happen. I never push data directly into the UI, but refresh the UI from underlying structures. We have data that can arrive asynchronously many times per second, but UI updates are throttled to about once every 650ms as a maximum.

    ReplyDelete
  3. If your question is "why can't you do either of these:

    TThread.Synchronize(nil, () =>
    Label1.Text := lValue.ToString);

    TThread.Synchronize(nil,
    begin Label1.Text := lValue.ToString; end);

    TThread.Synchronize(nil,
    Label1.Text := lValue.ToString);

    then the answer is "The Delphi language does not support lambda expressions, only anonymous methods".

    For an explanation of those, see these links:

    - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions
    - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-use-lambda-expressions-in-a-query
    - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-use-lambda-expressions-outside-linq
    - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/anonymous-methods

    If your question is "why do I need `TThread.Synchronize` at all" then the answer is that `Label1.Text := lValue.ToString` needs to be executed on the UI thread (usually the main thread) because neither the VCL nor the FMX UI thread is thread-safe.

    If you have to wait for that assignment to be processed, then you need to call `TThread.Synchronize`. If you do not have to wait, then a call to `TThread.Queue` would suffice. It would look like this:

    TThread.Queue(nil,
    procedure
    begin
    Label1.Text := lValue.ToString;
    end);

    Here I've assumed that `lValue` is a local variable (i.e. stack based and can be captured) to your outer method and cannot be overwritten by another thread. If that is not true, then you need to get the `lValue.ToString()` result into a local variable first so it can be captured.

    Explanations and of Queue:

    - https://stackoverflow.com/questions/42280937/delphi-queue-and-synchronize
    - http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Classes.TThread.Queue

    The `Queue` call will execute the anonymous method asynchronously and not wait for the completion. It basically encapsulates the thread-safe queue that Lars Fosdal was talking about.

    More on the capturing of variables:

    - https://stackoverflow.com/questions/5154914/how-and-when-are-variables-referenced-in-delphis-anonymous-methods-captured/5154920
    - http://interactiveasp.net/blogs/spgilmore/archive/2010/06/17/anonymous-methods-and-closures-in-delphi-2010.aspx
    - https://stackoverflow.com/questions/31193949/is-it-possible-to-capture-the-values-of-variables-local-to-a-delphi-anonymous-me

    ReplyDelete

Post a Comment