6

私の純粋なDotNETライブラリは、管理されていないデスクトップアプリケーション内のプラグインとして実行されます。GDIハンドルの問題を示しているように見えるクラッシュレポートの安定した(ただし低い)ストリームを取得しています(エラーメッセージなどのフォントがシステムフォントに戻り、あらゆる種類のコントロールの表示が壊れ、直後に大規模なクラッシュが発生します) )。

フォームにはコントロールがほとんどありませんが、ユーザーコントロールで多くのGDI+描画を行います。使用しているハンドルの数、またはリークしているハンドルの数を知る良い方法は何ですか?

ありがとう、デビッド

4

7 に答える 7

5

Ray Vega's answer のGDIViewから始めて、次のヒントを見つけました。

[DllImport("User32")] 
extern public static int GetGuiResources(IntPtr hProcess, int uiFlags);

  public static void GetGuiResourcesGDICount()      
  { 
      //Return the count of GDI objects.          
      Console.WriteLine("GDICount"+GetGuiResources(System.Diagnostics.Process.GetCurrentProcess().Handle, 0));      
  }

  private void button1_Click(object sender, System.EventArgs e)
  {
      GetGuiResourcesGDICount();
  }

GDIView は、リークされたのはフォント オブジェクトであると通知しました。次に、ロギング コードに への呼び出しを追加しGetGuiResourcesて、オブジェクトの作成がトリガーされた時点を検出しました。

私たちの場合、LabelUserControlがバックグラウンド ウィンドウで非表示になっているときに、コントロールのテキストが更新されました。これにより、GDI がフォント ハンドルをリークする可能性があります。Labelこれを修正するために、現在画面に表示されていない限りを更新しないようにロジックを変更しました。UserControl表示されたかどうかを判断するために、が最後に描かれた時期を記録しています。

于 2012-03-03T03:32:18.980 に答える
4

GDIViewを見てみましょう(これはフリーウェアです)。

GDIView は、すべてのプロセスで開かれた GDI ハンドル (ブラシ、ペン、フォント、ビットマップなど) の一覧を表示する独自のツールです。GDI ハンドルの種類ごとの合計数と、各ハンドルの詳細情報が表示されます。このツールは、ソフトウェアでの GDI リソース リークを追跡する必要がある開発者に役立ちます。

代替テキスト
(ソース: nirsoft.net )

自動更新はデフォルトで無効になっていますが、特定の間隔で有効にして構成できることに注意してください。Options -> Auto Refresh -> Every [N] seconds

于 2010-04-07T00:45:15.343 に答える
3

パフォーマンスモニターに加えて、古き良きタスクマネージャーを試すことができます。

[プロセス]タブを確認し、[ View> ]をクリックSelect Columns...して、GDIオブジェクトを確認します。

于 2010-03-20T12:46:19.563 に答える
2

私は過去に同じ種類の問題に対処しなければなりませんでした。アプリケーションが割り当てているGDIオブジェクトの数を調べるには、GDIUsageと呼ばれる無料のツールを使用できます。

私の場合、アプリケーションが10.000を超えるGDIオブジェクトを割り当てていたためにクラッシュしていました。これは、WindowsXPの厳しい制限です。調べる価値があるかもしれません。

私はここでこの問題についてブログを書きました:http:
//megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/

于 2010-03-20T12:49:01.093 に答える
1

TaskMgr.exeの[プロセス]タブから簡単に確認できます。[列の表示と選択]で、[GDIオブジェクト]にチェックマークを付けます。

あなたの説明は確かにハンドルリークと一致します。これは、マネージドプログラムでは実際には発生しないはずです。ファイナライザーは、Dispose()の呼び出しを忘れた場合に対処する必要があります。ガベージコレクションされたヒープスペースを大量に消費しない限り。また、管理されていないアプリがハンドルをリークしている可能性もあります。

于 2010-03-20T12:45:48.097 に答える
1

まだ行っていない場合は、必ずIDisposableを呼び出してください。使用しているGDI+図面オブジェクトを破棄してください。通常、これはC#usingコンストラクトを使用して行います。例:

using(Brush brush = ...)
{
    ...
}

FxCopやVisualStudioのTeamSystemエディションに組み込まれているバージョンなどの静的コード分析ツールは、Disposeの呼び出しに失敗した場合を検出するのに役立ちます。

この方法でDisposeを呼び出さないと、ガベージコレクターが適切であると判断するまでハンドルが再利用されないため、ハンドルリークが発生する可能性があります。

于 2010-03-20T12:47:58.550 に答える
1

GDIObjは、Feng Yuan が著書「Windows Graphics Programming: Win32 GDI and DirectDraw 」のサンプル プログラムとして提供している無料のユーティリティです。

タスク マネージャーとは異なり、DC、リージョン、ビットマップ、パレット、フォント、ブラシなど、さまざまな GDI ハンドル タイプの詳細な内訳のカウントを提供します。

(ただし、GDIViewはハンドルに関する詳細を提供しますが、カウント情報のみを提供します。)

于 2010-08-07T07:51:18.923 に答える