1

次のような小さなクラスから呼び出す大きな winform クラスがあります。

    void login()
    {           
        mainForm f1 = new mainForm();                
        f1.ShowDialog();
    }

mainForm は、ログイン後に大量のメモリを消費します (タスク マネージャーで確認します)。mainForm を閉じると、プログラムはログイン フォームに戻ります。このステップで、もう一度タスク マネージャーを確認すると、プログラムが mainForm が使用していたメモリを解放していないことがわかります。ログインした後、プログラムがクラッシュし、「メモリ不足」エラーが表示されます。

f1.Dispose()、f1=null、GC.Collect()、および見つけた他のすべてのメソッドをテストしたと言わざるを得ません。

ログインフォームを閉じたときにのみメモリが解放されます(Application.Runで使用される開始クラスです)

プログラムを閉じるときと同じように、mainForm インスタンス (f1) とこのフォームのすべてのリソースを破棄したいと考えています。

4

3 に答える 3

3

OOM がログイン フォームと関係があるかどうかはよくわかりません。また、Taskmgr.exe によって報告されるように、フォームを閉じたり破棄したりすることでメモリ使用量が減少することはまずありません。

しかし、あなたは間違いなく間違っています。ダイアログは、Winforms では異なる方法で処理されます。Show() で表示するフォームのように自動的に破棄されることはありません。必然的に、ダイアログを閉じた後にユーザーがダイアログに入力したものを取得する必要があります。これは、ダイアログが破棄されるときに危険です。だからあなたはそれを自分でしなければなりません。適切なパターンは次のとおりです。

    using (mainForm f1 = new mainForm()) {
        if (f1.ShowDialog() == DialogResult.Ok) {
            // Retrieve data entered by user and do something with it
            //...
        }
    }

usingステートメントを使用すると、ダイアログの結果を取得したにダイアログ インスタンスが確実に破棄されます。

于 2012-07-08T14:58:02.967 に答える
2

いくつかの考え:

于 2012-07-08T14:15:22.203 に答える
1

おそらく、メインフォームは表示時にそれ自体への参照を作成し、それが割り当てる参照/デリゲート/イベントをチェックし、メインフォームが完了したときにそれらが登録解除されていることを確認するか、イベントハンドラー (つまりアプリケーションイベント) を別のクラスに移動します。

これまでのところ、100% の確率で「.NET メモリ リークを発見」しましたが、そうではありませんでした! すべてのディスポーザブルを破棄し、参照を保持する静的をどうするかを監視し、重複したイベント サブスクリプションを作成せず、可能な場合はそれらを整理します。

mouters が言うように SOS を使用して、dispose を実行した後にメインフォーム クラスの gcroots をチェックし、GC.Collect(3) を数回呼び出します。参照がどこにあるかをトレースすると、バグが見つかるはずです。

于 2012-07-08T14:34:32.880 に答える