DOBON.NET DOBON.NETプログラミング掲示板過去ログ

呼び出し方の変更で、メモリ使用量が増大

環境/言語:[C#.net FW2.0]
分類:[.NET]

Formに配置したボタン押下時の処理を、同Form内のPublicメソッドにして、
実行するように変更しました。
すると、今までの3倍近くのメモリを消費するようになり、
OutOfMemoryが発生するようになりました。

処理内容自体は変えていないため、問題ないと思っていたのですが、
呼び出し方の違いで、メモリの扱いなどが変わるものなのでしょうか。

呼び出しは以下のように行っています。
From1 fm1 = new Form1()
fm1.testFunc();

変更前までは以下の呼び出しで、画面を表示して、ボタン押下で処理を実行
するようにしていました。
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

何か注意することなどがありましたら、ご教授ください。
2012/08/17(Fri) 20:54:03 編集(投稿者)

■No30827に返信(よしおさんの記事)
> 呼び出しは以下のように行っています。
> From1 fm1 = new Form1()
> fm1.testFunc();

このコードをどこに書いているのでしょうか?
加えて、その testFunc は Form1 にないとダメなのでしょうか?

おそらく、インスタンスの概念を正しく理解していただけていないことが問題だと思われますが、全体像をつかまないと、適切な助言がしづらいためにお聞きしています。
Azulean様

説明が分かりにくくて、申し訳ありません。

画面を起動してボタン押下で行っていた処理を、exeから直接起動する
ように修正をしました。
元ソースにあまり手を加えたくなかったため、Formの表示をせずに
関数をコールするようにしました。
(特にForm1にないといけない訳ではないです)

以前はProgramクラスのMainで以下の呼び出しを行っていました。
 Application.EnableVisualStyles();
 Application.SetCompatibleTextRenderingDefault(false);
 Application.Run(new Form1());

画面を表示させずに、ボタン押下処理と同様の処理を行いたかったため、
Form1のtestFunc()に処理を移して、ProgramクラスのMainで以下の呼び出しを
するように変更しました。
 From1 fm1 = new Form1()
 fm1.testFunc()
■No30831に返信(よしおさんの記事)

> 画面を表示させずに、ボタン押下処理と同様の処理を行いたかったため、
> Form1のtestFunc()に処理を移して、ProgramクラスのMainで以下の呼び出しを
> するように変更しました。
>  From1 fm1 = new Form1()
>  fm1.testFunc()
これを繰り返し処理しているということでしょうか?Form1のインスタンスを繰り返し作成し破棄することを行っていないためメモリ領域を食いつぶしているものと思われます。この実装が適切かはおいておいてtestFuncがインスタンスに依存する処理でなければ毎回newをしなければ余分なメモリを消費することはないかと思います。
shu様

> これを繰り返し処理しているということでしょうか?Form1のインスタンスを繰り返し作成し破棄することを行っていないためメモリ領域を食いつぶしているものと思われます。この実装が適切かはおいておいてtestFuncがインスタンスに依存する処理でなければ毎回newをしなければ余分なメモリを消費することはないかと思います。

繰り返しは行っていません。1回の呼び出しのみです。
testFunc()の内部では繰り返し処理を行っています。
(元のボタン押下時の処理と同じプログラムとなっています)
■No30835に返信(よしおさんの記事)

> 繰り返しは行っていません。1回の呼び出しのみです。
> testFunc()の内部では繰り返し処理を行っています。
> (元のボタン押下時の処理と同じプログラムとなっています)
そうするとtestFuncの処理中のインスタンス解放の障害が発生しているのではないでしょうか?
1回の呼び出しで繰り返し処理をしているということはメインスレッドでの処理をずっと継続して行っているという事になると思うのですがそうするとGCが動作するすきがなくなってしまっているのでは?長時間終わらない処理はメインスレッドではなくスレッドを分けるか、Timerにより処理を分割し一度に行う処理を短くした方がよいです。
shu様

返信ありがとうございます。
GCの強制的な解放をループ処理に入れてはみたのですが、
解放量が使用量に追いついていないようでした。

ただ、今回はボタン押下時から、メソッドに切りだしただけで発生したので、
Formでのメモリの扱いなどの、違いなどがあるのかと困惑している状況です。
(元々のプログラム自体にリーク不具合があるのでしょうが)
■No30842に返信(よしおさんの記事)
> ただ、今回はボタン押下時から、メソッドに切りだしただけで発生したので、
> Formでのメモリの扱いなどの、違いなどがあるのかと困惑している状況です。
> (元々のプログラム自体にリーク不具合があるのでしょうが)

正直なところ、そのコード特有の現象だと思われるため、第三者にはアドバイスが難しいです。
new をループで繰り返していないか、new そのものじゃなくても Create など新しいインスタンスやメモリを確保しそうなことを繰り返していないかを確認してみましょう。
■No30842に返信(よしおさんの記事)

> ただ、今回はボタン押下時から、メソッドに切りだしただけで発生したので、
> Formでのメモリの扱いなどの、違いなどがあるのかと困惑している状況です。
> (元々のプログラム自体にリーク不具合があるのでしょうが)
testFuncの中身がさっぱり分からないのでなんとも言えないです。
期間が開いてしまいましたが、ご報告します。

コンソールアプリケーションとして、再作成しなおしたところ
メモリーを大幅に消費する現状はなくなりました。
根本原因は分かっていません、調査は終了する事になりました。

アドバイスを頂き、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板