【问题标题】:Windows Service and TThreadWindows 服务和 TThread
【发布时间】:2015-09-26 19:03:19
【问题描述】:

我是 Windows 服务的新手,我需要做这项工作... 我从here 得到了我的代码,这只是这段代码的一个副本。但我正在尝试从服务中发出一些 HTTP 请求。对于这项工作,我选择创建一个新线程,并在线程内执行请求...这部分代码是(这是我从上面链接的原始代码中添加的唯一内容):

type
  MyThread = class(TThread)
  strict private

  protected
    constructor Create;
    procedure Execute; override;
  end;

constructor MyThread.Create;
begin
  inherited Create(false);
  FreeOnTerminate:= true;
  Priority:= tpNormal;
end;

procedure MyThread.Execute;
var
  IdHTTP: TIdHTTP;
begin
  while not(Terminated) do
  begin
    IdHTTP := TIdHTTP.Create(nil);
    IdHTTP.Get('http://google.com');
    IdHTTP.Free;
    Sleep(5000);
  end;
end;

我在 OnServiceCreate 内部调用 MyThread.Create 过程,但它只发出一个请求。它不应该每 5 秒执行一个请求,而 Thread 还活着?

【问题讨论】:

    标签: delphi


    【解决方案1】:

    我在 OnServiceCreate 内部调用 MyThread.Create 过程

    TService.OnCreate 事件是创建线程的错误位置。该事件不仅在服务启动时触发,而且在(卸载)服务时触发。而是在OnStart事件中创建线程,该线程只有在服务启动时才会触发。

    它只发出一个请求。它不应该每 5 秒执行一个请求,而 Thread 还活着?

    您的线程没有进行任何错误处理。如果TIdHTTP.Get() 因任何原因失败,它会引发您没有捕获的异常,因此您的线程将自行终止。

    也没有理由在每次循环迭代时重新创建 TIdHTTP 对象。

    我强烈建议你不要使用FreeOnTerminate=true。将其保留为 false,然后在 OnStop/OnShutdown` 事件中终止并释放线程。

    试试这样的:

    type
      MyThread = class(TThread)
      protected
        procedure Execute; override;
      public
        constructor Create;
      end;
    
    constructor MyThread.Create;
    begin
      inherited Create(False);
    end;
    
    procedure MyThread.Execute;
    var
      IdHTTP: TIdHTTP;
    begin
      IdHTTP := TIdHTTP.Create(nil);
      try
        while not Terminated do
        begin
          try
            IdHTTP.Get('http://google.com');
            // success, do something
          except
            // failed, do something else
          end;
          Sleep(5000);
        end;
      finally
        IdHTTP.Free;
      end;
    end;
    

    type
      TService1 = class(TService)
        procedure ServiceStart(Sender: TService; var Started: Boolean);
        procedure ServiceStop(Sender: TService; var Stopped: Boolean);
      private
        Thread: MyThread;
      end;
    
    procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
    begin
      Thread := MyThread.Create;
      Started := True;
    end;
    
    procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
    begin
      if Thread <> nil then
      begin
        Thread.Terminate;
        while WaitForSingleObject(Thread.Handle, WaitHint-100) = WAIT_TIMEOUT do
          ReportStatus;
        FreeAndNil(Thread);
      end;
      Stopped := True;
    end;
    

    【讨论】:

    • 是的,谢谢你对ServiceStart/Stop的解释……原来的代码,没有这个实现。我会尝试将它带到我的代码中,无论如何该请求已通过 try/except 解决,所以一切都很好。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多