質問者
System.ComponentModel.BackgroundWorker や DataSetのDispose

質問
-
こんばんは。もんたといいます。
いま、Windows Forms アプリケーションでBackgroundWorkerクラスを使って実装しようとしています。
デザインモードでFormにBackgroundWorkerを貼り付けて、実装しています。
そこで、ふと気になったのですが、BackgroundWorkerのインスタンスって、いつDisposeされるのだろう?と思いました。BackgroundWorkerはControlじゃないので、FormのClose時に一緒にDisposeされません。
同様の理由で、DataSetもDisposeされないのでは?と思っています。
そこで質問ですが、このように、System.ComponentModel.ComponentクラスのインスタンスのDisposeって、どのように実装すればよいか、教えていただけないでしょうか?
よろしくおねがいします。
すべての返信
-
>同様の理由で、DataSetもDisposeされないのでは?と思っています。
BackgroundWorkerについてはよくわからないのですが、DataSetではDisposeに何も実装されていません。つまり、Disposeを実行しても何の変化もありません。
>そこで質問ですが、このように、System.ComponentModel.ComponentクラスのインスタンスのDisposeって、どのように実装すればよいか、教えていただけないでしょうか?
一般的にはアンマネージリソースの開放、また、クラスのインスタンスメンバーで巨大なメモリーを消費するような場合で、クラスのインスタンスは存続し続けながらそれを開放したい場合などは、用意した方がいいでしょう。いや、すべきでしょう。
-
BackgroundWorker や DataSet は Dispose() は誰も呼ばないのが通例です。
Visual Studio のフォームデザイナは、「Component の派生クラス かつ Control の派生クラスではない かつ Dispose メソッドを実装しているもの」をフォーム自身の components コレクションに登録して管理します。BackgroundWorker や DataSet では、Dispose メソッドを実装していないため「Dispose を行う必要がない」と判断されて、フォームの Dispose() からの連携対象外として扱われているわけです。
※ Component クラスを派生しているのは、Visual Stuido のようなデザイナがツールボックスに登録するための親クラスとして要求するためです。
-
随分昔のスレッドですね。
K.Takaoka さん
> BackgroundWorker や DataSet は Dispose() は誰も呼ばないのが通例です。
デザイナで使用するかどうかに関係なく、本当は不要になった時点で呼ばれるべき(呼ぶべき)と私は思いますけどね。。。
> BackgroundWorker や DataSet では、Dispose メソッドを実装していないため「Dispose を行う必要がない」と判断されて、フォームの Dispose() からの連携対象外として扱われているわけです。
両方とも Dispose メソッドは実装していますので、条件としては、インターフェイスを「明示的に」実装しているかどうかでしょうか?
Component がすでにパターンにのっとって Dispose を実装していますので、おそらく Component の派生クラスが明示的に Dispose を実装することは実質ありえないのかなと思いました。
すると、本来は明示的かどうかに関係なく、実装していれば components に登録されるべきじゃないかと思いました。
なので、なんとなく設計ミスのような気がしました。
追記:
試してみればわかることでしたが、K.Takaoka さんが言いきられていたので、一部間違ってるだけで大筋はあってると信じてしまいました。
と書くと、K.Takaoka さんに対する嫌味になっちゃいますが、自分のために書かせてもらいます。(^^; 性格が悪くてすみません。。- 編集済み TH01 2010年12月7日 7:34 追記
-
そういうことですか、納得しました。
以下のコードで試すと、確かにそうなりました。
自動的に Add されるんじゃなくて、デザイナのコードが components を渡してくれるから、そこに自分で Add するんですね。
public class MyComponent : Component
{
public MyComponent() : base() { }
public MyComponent(IContainer container) : this()
{
container.Add(this);
}
protected override void Dispose(bool disposing)
{
// デザイナの components.Dispose(); 時に、
// ここがちゃんと呼び出されました。
base.Dispose(disposing);
}
}