Delphi TThread under ARC (iOS) not being released

前端 未结 1 1245
暗喜
暗喜 2021-02-19 16:30

What is a proper way to terminate a thread using Delphi for iOS under ARC management?

Take this simple example:

  TMyThread = class(TThread)
  protected
         


        
1条回答
  •  说谎
    说谎 (楼主)
    2021-02-19 17:01

    After some digging in qc the following issues and workaround show up:

    Thread parameters should be passed as const

    function ThreadProc(Thread: TThread): Integer;  <<-- pass_by_reference pushes
    var                                                  up the ref_count.
      FreeThread: Boolean;
    begin
      TThread.FCurrentThread := Thread;
    

    Had you passed it as const the ref_count would have not gone up to 3. Normally this is not a problem, because the ref_count gets decreased on exit of the function, but here:

    the function epilog is never exectued because pthread_exit() jumps out of the code.

    This is only part of the solution though, quite a bit more needs to be done...

    Full workaround by Dave Nottage

    After much fiddling around, I've come up with this potential workaround:

    Make these mods to the Classes unit: Change:

    function ThreadProc(Thread: TThread): Integer;
    

    to:

    function ThreadProc(const Thread: TThread): Integer;
    

    and add:

    TThread.FCurrentThread := nil;
    

    after this line:

    if FreeThread then Thread.Free;
    

    Override DoTerminate in the TThread descendant, thus:

    procedure TMyThread.DoTerminate;
    begin
      try
        inherited;
      finally
        __ObjRelease;
      end;
    end;
    

    Call the thread thus:

    FMyThread.Free; // This will do nothing the first time around, since the reference will be nil
    FMyThread := TMyThread.Create(True);
    // DO NOT SET FreeOnTerminate
    FMyThread.OnTerminate := ThreadTerminate;
    FMyThread.Resume;
    

    This (at least for me, on the device) results in the thread being destroyed on subsequent calls.

    NOTE: Under ARC conditions, never declare a reference to a thread locally, because when it falls out of scope, the thread is destroyed and the Execute method is never called, not to mention other problems it causes.

    0 讨论(0)
提交回复
热议问题