1

.NET CF アプリケーションでメモリ リークの問題があります。

RPMを使用して、動的に作成するコントロールが期待どおりにガベージ コレクションされないことを確認しました。.NET ウィンドウ フォームで同じコードを実行すると、動作が異なり、期待どおりにコントロールが破棄されます。

プロセス ヒープカウンターの PerfMon 経由の RPM からの出力を参照してください。
代替テキスト

GC ヒープ:
代替テキスト

私の推測では、パネルへの弱い参照は、なんらかの不明な理由でオブジェクトを GC の対象にできないのではないでしょうか?

注: Dispose()はサンプルの問題を解決しますが、オブジェクトが使用されなくなった時期を明確に判断できないため、既存のアプリケーションに簡単に組み込むことはできません。

問題を説明するために、ソースの簡略版を含めました。

using System;
using System.Windows.Forms;

namespace CFMemTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Calling this event handler multiple times causes the memory leak
        private void Button1_Click(object sender, EventArgs e)
        {
            Panel uc = new Panel();
            // Calling uc.Dispose() cleans up the object 
        }
    }
}

更新:
1. GC.Collect() を呼び出しても、パネルがクリーンアップされません。
2. Windows CE 4.2 デバイスで .NET CF 2.0 SP1 を使用します。

4

4 に答える 4

3

この動作を説明する追加情報がここにあります。

イリヤ・トゥマノフによると

NETCF に関連するすべての UI は、意図的に GC スコープから除外されるため、収集されることはありません。この動作はデスクトップとは異なり、NETCF V3.5 で変更されています (互換モードで実行されている場合を除く)。

NETCF のマネージ UI クラスはデスクトップとはまったく異なるため、非常に異なります。これらは、許容できるパフォーマンスを達成するために必要なネイティブ実装の薄いラッパーです。

そのようなリソースがあるかどうかはわかりません。しかし、実際に知っておく必要があるのは、収集されることはなく、dispose を呼び出さなければならないということだけです。実際にはデスクトップでもそれを行う必要がありますが、そうしないともっと寛容になります。NETCF ではそうではありません。

于 2008-10-15T07:29:00.663 に答える
2

フォームは、その存在を知る方法がないため、コードで作成されたすべてのコントロールを自動的に破棄しません。Form to Form を取得して Disposed 時に自動的に Dispose するには、それを Controls コレクションに追加する必要があります。

あなたの場合、それは何もしないかもしれません。あなたの例が人為的なものなのか、それとも現実のものなのかはわかりません。現実世界の場合、変数がスコープ外になると Panel が収集されないため、動作は予想されます (デスクトップでも発生するかどうかはわかりません)。コレクションに使用できるようになりますが、これは次のコレクション パスでスイープされることを意味します。GC を引き起こさない限り、解放されることはありません。

CF のメモリ管理に関する MSDN Web キャストをご覧になることを強くお勧めします。内部で何が起こっているかについて、ここで回答するよりもはるかに詳細な説明を提供します。

于 2008-10-14T20:33:26.400 に答える
1

本当にメモリリークがありますか?.NET Compact Framework ガベージ コレクターの動作は、完全な .NET Framework のものとは少し異なります。Steven Pratschner のブログから:

コレクションは、次のいずれかの場合に開始されます。

  • 1MB のオブジェクトが割り当てられました。

  • アプリケーションをバックグラウンドに移動し、

  • メモリの割り当てに失敗しました

  • アプリケーションが GC.Collect を呼び出します。

于 2008-10-14T11:37:05.127 に答える