0

html ヘルプを使用する Delphi 2007 で書かれたプログラムがあります。非常に頻繁に終了時にハングアップし (実際には html ヘルプが呼び出されていなくても)、Windows.pas のファイナライズ セクションでこの呼び出しまで問題を突き止めました。

finalization
  if HtmlHelpModule <> 0 then FreeLibrary(HtmlHelpModule);
end.

hhctrl.ocx のアンロード コードの奥深くにある NTWaitFormMultipleObjects が原因で、この呼び出しでメイン スレッドがハングします。明らかに同じものを待機している他のスレッド (私のコードが作成するスレッドはありません) があるため、プログラムがハングします。これらのスレッドのいくつかは、ADO や Microsoft SQL Server クライアント ライブラリによって作成されていると思います。

私は 1 つの回避策を見つけました: LoadLibrary('hhctrl.ocx') への追加の呼び出しなので、Windows.pas の FreeLibrary への呼び出しは実際には dll をアンロードせず、参照カウントを 1 に減らすだけです。気分が悪いわけではありません。

これは既知の問題ですか? 適切な解決策はありますか?

(はい、私はグーグルで検索しましたが、役立つものは何も見つかりませんでした。これは同様の問題を説明しているよう です-hangs-on-unload?forum=vcgeneral と別の DLL を使用します。)

編集:いくつかの詳細情報:

この問題は、プログラム内で html ヘルプがまったく呼び出されない場合 (つまり、LoadLibrary('hhctl.ocx') が呼び出されなかった場合) にのみ発生するようです。シャットダウン時に、htmlhelp.pas のファイナライズ コードは、すべての htmlhelp ビューアー ウィンドウ (ウィンドウがないもの) を閉じようとし、HtmlHelp 関数への最初の呼び出しを発行します。これにより、windows.pas で LoadLibrary が呼び出されます。プログラムで htmlhelp を表示すると、すべて正常に動作します。したがって、これは RTL のファイナライズ内で LoadLibrary('hhctl.ocx') を呼び出す際の問題である可能性があると思います。しかし、これを回避する方法がわかりません。

4

2 に答える 2

-1

通常、ホスト アプリケーションを閉じると、Windows は、このアプリケーションによって開かれたすべてのヘルプ ウィンドウを自動的に閉じます。問題があります...これにより、アクセス違反が発生する可能性があります。

私は Delphi プログラマーではありません。ヘルプ オーサリング (CHM) と VB で忙しいです。HH_INITIALIZE、HH_UNINITIALIZE コマンドを使用してみることができます。これらは、HH ワークショップのオンライン ヘルプに記載されています。ただし、コードの HH_CLOSE または HH_CLOSE_ALL も確認してください。

早めに HH_CLOSE_ALL を呼び出してください。HH_CLOSE_ALL と UnloadLibrary への呼び出しの間のスペースを増やします。VB と Delphiでは、Form Close または DestroyではなくForm QueryUnload で呼び出しを実行します。

回避策として、HH ウィンドウを手動で閉じるか、CloseQuery() イベントの早い段階で閉じ、sleep(0) を使用して HTMLHelp が落ち着くまで数サイクルを与えます。

//Will close all Help windows opened by the application - no handle required
HtmlHelp(0, nil, HH_CLOSE_ALL, 0);

また

//This runs a little faster
if IsWindow(_HHwinHwnd) then
SendMessage( _HHwinHwnd, wm_close, 0, 0 );

サンプル:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   //if IsWindow(_HHwinHwnd) then
   //  SendMessage( _HHwinHwnd, wm_close, 0, 0 );
   HtmlHelpA(0, nil, HH_CLOSE_ALL, 0);
   Sleep(0);
end;

シャットダウン時にやみくもに HH_CLOSE_ALL を呼び出さないでください。ユーザーが HTML ヘルプをインストールしていない場合、この呼び出しによってアプリケーションがクラッシュします。これはより安全なコードです。HtmlHelp() を呼び出す前に、HH がインストールされているかどうかを確認していることに注意してください。

procedure HHCloseAll;
begin
  If @HH.HtmlHelp <> Nil then  //HH API is available
    begin
    HH.HtmlHelp(0, nil, HH_CLOSE_ALL, 0);
    Sleep(0); 
  end;
end;
于 2016-01-30T13:20:57.660 に答える