2016-03-28 1 views
2

私は、ユーザーが別のフォームから開くことができる形式を持つが生成されますブロック。フォームには、フォームの外部で保持される静的なBindingListsにバインドされたいくつかのコントロールがあり、これらのリストを変更するとイベントがトリガーされます。アンデッドフォームはまだイベント

後でユーザーがこのフォームの別のコピーを開くと、元のフォームのイベントが閉じられていても実行中であることがわかります。

どうすればいいですか?このことを強制終了するにはどうすればいいですか?心を通ってステーク?

更新:コメントに示されているように、静的なBindingListオブジェクトは古いフォームへのデータバインディングを維持していました。私にとっては、解決策はBindingListオブジェクトを取り除くことでした。なぜなら、とにかくデータバインディングプロパティを意図的に使用していないからです。

+3

イベントの登録を解除する可能性はありますか?バインディングの設定を解除しますか? –

+1

@MeirionHughes - 私はそうだと思いますが、私の本当の疑問は、どうしてこのフォームを処分しないのですか? –

+6

廃棄は、GCによって決してクリーンアップされない_unmanaged_リソースをクリーンアップする場合にのみ使用します。これは一般的なクリーンアップに使用できますが、元々は管理されていないクリーンアップ用です。最後に、オブジェクトイベントハンドラの登録を解除しないと、オブジェクトは孤立しておらず、GCは解放できません。それでそれは生き続けるでしょう。 –

答えて

1

現時点では、イベントハンドラとデータバインディングを無視すると、コードは現時点では少し残忍です。あなたはわずかにこれを得ることができます:

using (frmReport EditReport = new frmReport()) 
{ 
    EditReport.ShowDialog(); 
} 

あなたはそれがフォームがとにかく閉じたあなた.Close()コールになった時点でダイアログとしてそれを示していると。 usingの文は.Dispose()を呼び出します。

フォームを廃棄するときは、基本的に親からフォームを削除しています(すべての子コントロールを破棄し、Windowsハンドルを解放します)。

ただし、イベントハンドラのデタッチ方法はわかりませんし、データバインディングの削除方法もわかりません。これらのことはフォームへの参照であるため、ガベージコレクタはフォームをライブオブジェクトとしてカウントし、収集しようとはしません。

したがって、フォーム内に外部イベントを受信するハンドラがあり、そのイベントが発生するとフォームはそれらを処理しようとします。

フォームを閉じるときに、すべてのハンドラを切り離してすべてのデータバインディングをアンバインドする必要があります。

2回目にフォームを開くと、最初のフォームと直接関係はありませんが、データソースでイベントの発生や値の更新が発生し、元のフォームがトリガーされた可能性があります。

+0

私のコードは、過剰殺戮は「殺す」ことを意味しているので、「過剰殺戮」ではありません。私が質問した理由は誰も殺していないということです。私は、私が試したものと失敗したものを見せつけて、殺す試みをしました。問題の原因は静的なBindingListsが古いフォームへのデータバインディングを維持していたため、これを答えとしてマークしました。 –

0

一般的に、私はイベントからの退会後に呼び出されることを許容するためにイベントサブスクリプションコードを書くことをお勧めします。これはさまざまな方法で起こります。

私はあなたがやった実験はなく、例えば、あなたがこれを書いている場合かわからない:

private void btnEditTemplate_Click(object sender, EventArgs e) 
{ 
    using (frmReport EditReport = new frmReport()) 
    { 
    EditReport.ShowDialog(); 
    EditReport.Close(); 
    EditReport.Dispose(); 
    } 
    using (frmReport EditReport2 = new frmReport()) 
    { 
    EditReport2.ShowDialog(); 
    EditReport2.Close(); 
    EditReport2.Dispose(); 
    } 
} 

その後、まだまで処理得ることはありません最初のダイアログのメッセージキュー内のイベントがあるかもしれません2番目のインスタンスのShowDialog()呼び出しでモーダルメッセージループを入力します。

Dispose()を使用しても、ガベージコレクタは、メッセージキュー内のこれらのサブスクリプションへの参照のため、最初のオブジェクトを再要求しません。彼らが配信されているオブジェクトがすでに破棄されている場合は、何もしないようにイベント購読を書き込むと、何の害もありません。チェックするものは、使用している基本クラスによって異なります。最悪の場合、独自のIsDisposedまたはIsClosedインスタンス変数を実装します。

+0

フォームから、すべてのイベントからフォームの外にある長命のオブジェクトの購読を解除する必要があります。そうしなければ、それらのサブスクリプションは、オブジェクトの外側にある限り、オブジェクトをメモリに保持します。私はそれがあなたが扱っている問題ではないと仮定しています。 –