1

TIdHTTPServerいくつかの理由で、のインスタンスをDLLに入れる必要があります。これは次のように行われます。

インターフェースユニット:

unit DLL.Intf;

interface

type
  IServer = interface
    procedure DoSomethingInterfaced();
  end;

implementation

end.

サーバーのコンテナ:

unit Server;

interface

uses
  DLL.Intf,
  IdHTTPServer,
  IdContext,
  IdCustomHTTPServer;

type
  TServer = class(TInterfacedObject, IServer)
  private
    FHTTP: TIdHTTPServer;
    procedure HTTPCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
      AResponseInfo: TIdHTTPResponseInfo);
    procedure DoSomethingInterfaced();
  public
    constructor Create();
    destructor Destroy(); override;
  end;

function GetInstance(): IServer;

implementation

uses
  SysUtils;

var
  Inst: IServer;

function GetInstance(): IServer;
begin
  if not Assigned(Inst) then
    Inst := TServer.Create();

  Result := Inst;
end;

constructor TServer.Create();
begin
  inherited;
  FHTTP := TIdHTTPServer.Create(nil);
  FHTTP.OnCommandGet := HTTPCommandGet;
  FHTTP.Bindings.Add().SetBinding('127.0.0.1', 15340);
  FHTTP.Active := True;
end;

destructor TServer.Destroy();
begin
  FHTTP.Free();
  inherited;
end;

procedure TServer.DoSomethingInterfaced();
begin

end;

procedure TServer.HTTPCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
  AResponseInfo: TIdHTTPResponseInfo);
begin
  AResponseInfo.ContentText := '<html><h1>HELLO! ' + IntToStr(Random(100)) + '</h1></html>';
end;

end.

DLLはGetInstance()関数をエクスポートします:

library DLL;

uses
  SysUtils,
  Classes,
  Server in 'Server.pas',
  DLL.Intf in 'DLL.Intf.pas';

{$R *.res}

exports
  GetInstance;

begin
end.

メインのEXEファイルを終了するまで、サーバーが読み込まれ、正常に動作します。デバッガーは、メインスレッドがでハングすることを示していますFHTTP.Free();

EXEプロジェクトとDLLプロジェクトの両方で「ランタイムパッケージを使用してビルド」オプションを使用しているため、スレッドの同期について心配する必要はないと思いました。

このハングを修正するにはどうすればよいですか?

4

2 に答える 2

2

私の解決策は、アプリケーションのメイン フォームを閉じるときにActiveプロパティをTIdHTTPServertoに設定することでした。false

メッセージループを終了する前に、サーバーはすべてのスレッドを停止し、メインスレッドと同期する必要があると思います。

背後にあるメカニズムを説明する場合は、別の回答が正しいかどうかを確認します。

于 2012-09-14T11:04:59.973 に答える
1

TIdHTTPServer説明したことは、コードがイベント内のメインスレッドと同期している場合にのみ発生するはずですOnCommandGet. しかし、あなたが示したコードではそうしていないので、TIdHTTPServerデストラクタが正常に終了するのを妨げるものは何もないはずです. 内部的に、デストラクタはActiveプロパティを False に設定し、アクティブなスレッドが完全に終了するのを待ちます。内部の何もTIdHTTPServerメインスレッドと同期しません。TIdHTTPServerメイン スレッドとの同期中にメイン スレッドから非アクティブ化すると、デッドロックが発生します (呼び出しもTThread.Synchronize()ランタイムパッケージが無効になっている場合、一般的にDLL内にありますが、そうではありません)。したがって、あなたが説明することは意味がありません。実際のデッドロックを見つけるには、デバッガー内で TIdHTTPServer デストラクタをステップ実行する必要があります。

于 2012-09-14T23:04:11.333 に答える