Jump to content

Primož Gabrijelčič

Members
  • Content Count

    154
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by Primož Gabrijelčič


  1. IDE Fix Pack 6.4.3 breaks compilation in Rio 10.3.2 for our flagship application. After compile or rebuild, I get

     

    [dcc32 Fatal Error] FAB .gRPC  . pas ( 265): F2084 Internal Error: AV0D0F16E4(0D080000)-R0000000C-0

     

    Wihout IDE Fix Pack, compilation works fine.

     

    Any suggestions?

     

    • Like 1

  2. Hi all,

     

    Somehow I think that the following code should compile, but it does not. It looks like the compiler uses the wrong `TCallback` definition when resolving the property. Am I correct or did I miss something and I'm just stupid?

     

    program Project184;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils;
    
    type
      TCallback = reference to procedure (value: int64);
    
      TRunner = class
      public type
        TCallback = reference to procedure;
      strict private
        FOnCallback: TCallback;
      public
        procedure Run;
        property OnCallback: TCallback read FOnCallback write FOnCallback;
      end;
    
    procedure TRunner.Run;
    begin
      OnCallback(); // <-- E2035 Not enough actual parameters
    end;
    
    begin
    end.


    Delphi 10.3.1, in case this is a regression bug.


  3. Tricky, got me completely dazzled for a moment 🙂

     

    You are now generating new capture proc for each `I`. That `Proc`, however, is just a pointer. Now your code `Task.Invoke(procedure begin Proc(); end);` captures this `Proc` by value and executes the last stored value three times. 

     

    You should do it like this:

     

    function CaptureValue(Value: Integer): TOmniTaskInvokeFunction;
    begin
      Result := procedure begin Memo.Lines.add(Value.ToString); end;
    end;
    
    for I := 0 to 2 do
      begin
        Task.Invoke(CaptureValue(i));
      end;

     


  4. 43 minutes ago, stevegill said:

    In the first code snippet, if I dynamically created and destroyed database components in the Async part of the code, I'm assuming that they would be completely isolated from the main thread.  Is that correct?

     

    Indeed it is.


  5. If I understand correctly, this has nothing to do with a pipeline. a) You "create a protocol" (whatever that means) b) You submit that protocol to a background thread to execute it and c) you repeat step b. And you can do all that with different protocols.

     

    As one protocol is a normal serial process, it has nothing to do with threading. Just implement "protocol runner" as a state machine. 

     

    Then create a Background Worker abstraction and submit it work items. One work item = one "protocol runnner".

     

     

    • Thanks 1

  6. I don't really understand your questions, sorry.

     

    If you run some external code, you cannot be sure if it is thread-safe. You should protect access to it with some synchronization mechanism. 

     

    A whole idea of a guardian object with a "not responding" callback is new to me. I don't believe it is a commonly used pattern. I can't comment on it as I never used it in practice.


  7. By debugging, of course. Although, I have to admit, it had me quite stumped for a while.

     

    A bit of logging proves that service start and stop both come from the same thread (the first number is the thread id):

     

    8996|ServiceCreate
    8996|Servizio attivato porta = 8889
    17284|ServiceStart
    8996|Got message 1024
    8996|Keep Alive
    8996|Got message 1024
    8996|Keep Alive
    17284|A try to stop task...
    6456|Sending COmniTaskMsg_Terminated
    17284|FRunner.ExitCode = 0
    17284|ServiceStop
    8996|Got Terminated
    8996|OnTaskTerminated?
     

    8996 is the main service thread, 17284 is the service control thread, 6456 is the thread running the background task.

    

    • Thanks 1

  8. Your task is created in one thread (main service thread) and that thread processes messages sent from the task, including the termination message.

     

    The task is stopped from a different thread. ServiceCreate and ServiceStart/ServiceStop are NOT executed from the same thread.

     

    The OtlTaskControl code expects that the task will be terminated from the same thread that it was created in. The .Terminate method therefore tries to process all messages waiting in the message queue (for example, the termination message), but it cannot do that as the message queue is not associated with the "ServiceStop" thread but with the "ServiceCreate" thread.

     

    After the ServiceStop exits, the main service thread is destroyed and that destroys the IOmniTaskControl object. At that moment, messages from the inter-thread message queue are processed, but they cannot be dispatched anywhere as the main service thread is being terminated. (Because of a DSiWin32.pas bug, messages will still be dispatched and may cause the program to crash. This will be fixed today.)

     

    Solution? Just do your OnTerminated processing in ServiceStop.

     


  9. I can't tell the reason for your problem from the example you've given. Please post a minimal, compilable, and complete project that exhibits the problem and I'll look into it. It would be also good if you can drop dependency on WebBroker when preparing that project.

×