代码之家  ›  专栏  ›  技术社区  ›  jpfollenius Rob Kennedy

在Delphi2010中恢复挂起的线程?

  •  16
  • jpfollenius Rob Kennedy  · 技术社区  · 15 年前

    D2010中不推荐使用TThread的resume方法。所以,我认为它现在应该是这样工作的:

    TMyThread = class (TThread)
    protected
      Execute; override;
    public
      constructor Create;
    end;
    ...
    
    TMyThread.Create;
    begin
      inherited Create (True);
      ...
      Start;
     end;
    

    我错过了什么?

    2 回复  |  直到 15 年前
        1
  •  19
  •   Shadow Wizard    13 年前

    The reason is that a Thread is not supposed to start itself .

    类似的情况也存在 :没有 数据集 构造函数应该调用 ,或设置 活动:=真 .

    blog entry by Wings of Wind

    你应该:

    TThread用法说明 :

    基本上,线程应该是这样的:执行代码的上下文的封装。

    通过将这两者解耦,您获得了很大的灵活性,尤其是从多个位置启动业务逻辑(这在编写单元测试时非常方便!)。

    这是您可以使用的框架类型:

    unit DecoupledThreadUnit;
    
    interface
    
    uses
      Classes;
    
    type
      TDecoupledThread = class(TThread)
      strict protected
        //1 called in the context of the thread
        procedure DoExecute; virtual;
        //1 Called in the context of the creating thread (before context of the new thread actualy lives)
        procedure DoSetUp; virtual;
        //1 called in the context of the thread right after OnTerminate, but before the thread actually dies
        procedure DoTearDown; virtual;
      protected
        procedure DoTerminate; override;
        procedure Execute; override;
      public
        constructor Create;
        procedure AfterConstruction; override;
      end;
    
    implementation
    
    constructor TDecoupledThread.Create;
    begin
      // create suspended, so that AfterConstruction can call DoSetup();
      inherited Create(True);
    end;
    
    procedure TDecoupledThread.AfterConstruction;
    begin
      // DoSetUp() needs to be called without the new thread in suspended state
      DoSetUp();
      // this will unsuspend the underlying thread
      inherited AfterConstruction;
    end;
    
    procedure TDecoupledThread.DoExecute;
    begin
    end;
    
    procedure TDecoupledThread.DoSetUp;
    begin
    end;
    
    procedure TDecoupledThread.DoTearDown;
    begin
    end;
    
    procedure TDecoupledThread.DoTerminate;
    begin
      inherited DoTerminate();
      // call DoTearDown on in the thread context right before it dies:
      DoTearDown();
    end;
    
    procedure TDecoupledThread.Execute;
    begin
      // call DoExecute on in the thread context
      DoExecute();
    end;
    
    end.
    

    您甚至可以通过以下方式使其基于事件:

    unit EventedThreadUnit;
    
    interface
    
    uses
      Classes,
      DecoupledThreadUnit;
    
    type
      TCustomEventedThread = class(TDecoupledThread)
      private
        FOnExecute: TNotifyEvent;
        FOnSetUp: TNotifyEvent;
        FOnTearDown: TNotifyEvent;
      strict protected
        procedure DoExecute; override;
        procedure DoSetUp; override;
        procedure DoTearDown; override;
      public
        property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
        property OnSetUp: TNotifyEvent read FOnSetUp write FOnSetUp;
        property OnTearDown: TNotifyEvent read FOnTearDown write FOnTearDown;
      end;
    
      // in case you want to use RTTI
      TEventedThread = class(TCustomEventedThread)
      published
        property OnExecute;
        property OnSetUp;
        property OnTearDown;
      end;
    
    implementation
    
    { TCustomEventedThread }
    
    procedure TCustomEventedThread.DoExecute;
    var
      TheOnExecute: TNotifyEvent;
    begin
      inherited;
      TheOnExecute := OnExecute;
      if Assigned(TheOnExecute) then
        TheOnExecute(Self);
    end;
    
    procedure TCustomEventedThread.DoSetUp;
    var
      TheOnSetUp: TNotifyEvent;
    begin
      inherited;
      TheOnSetUp := OnSetUp;
      if Assigned(TheOnSetUp) then
        TheOnSetUp(Self);
    end;
    
    procedure TCustomEventedThread.DoTearDown;
    var
      TheOnTearDown: TNotifyEvent;
    begin
      inherited;
      TheOnTearDown := OnTearDown;
      if Assigned(TheOnTearDown) then
        TheOnTearDown(Self);
    end;
    
    end.
    

    unit TestCaseThreadUnit;
    
    interface
    
    uses
      DecoupledThreadUnit,
      TestFramework;
    
    type
      TTestCaseRanEvent = procedure (Sender: TObject; const TestResult: TTestResult) of object;
      TTestCaseThread = class(TDecoupledThread)
      strict private
        FTestCase: TTestCase;
      strict protected
        procedure DoTestCaseRan(const TestResult: TTestResult); virtual;
        function GetTestCase: TTestCase; virtual;
        procedure SetTestCase(const Value: TTestCase); virtual;
      protected
        procedure DoExecute; override;
        procedure DoSetUp; override;
        procedure DoTearDown; override;
      public
        constructor Create(const TestCase: TTestCase);
        property TestCase: TTestCase read GetTestCase write SetTestCase;
      end;
    
    implementation
    
    constructor TTestCaseThread.Create(const TestCase: TTestCase);
    begin
      inherited Create();
      Self.TestCase := TestCase;
    end;
    
    procedure TTestCaseThread.DoExecute;
    var
      TestResult: TTestResult;
    begin
      if Assigned(TestCase) then
      begin
        // this will call SetUp and TearDown on the TestCase
        TestResult := TestCase.Run();
        try
          DoTestCaseRan(TestResult);
        finally
          TestResult.Free;
        end;
      end
      else
        inherited DoExecute();
    end;
    
    procedure TTestCaseThread.DoTestCaseRan(const TestResult: TTestResult);
    begin
    end;
    
    function TTestCaseThread.GetTestCase: TTestCase;
    begin
      Result := FTestCase;
    end;
    
    procedure TTestCaseThread.SetTestCase(const Value: TTestCase);
    begin
      FTestCase := Value;
    end;
    
    procedure TTestCaseThread.DoSetUp;
    begin
      if not Assigned(TestCase) then
        inherited DoSetUp();
    end;
    
    procedure TTestCaseThread.DoTearDown;
    begin
      if not Assigned(TestCase) then
        inherited DoTearDown();
    end;
    
    end.
    

    --杰罗恩

        2
  •  14
  •   Uwe Raabe    15 年前

    简短回答:调用继承的Create(false)并忽略开始!