none
アプリケーションを[×]で終了させる直前のデータ保存方法(ApplicationExitイベントハンドラ)について RRS feed

  • 質問

  • 続けての質問で恐縮ですがよろしくお願いします。

    アプリケーションをフォーム右上の[×]で終了させる場合に、その直前でアプリケーションが保持しているデータをテキストファイルに保存しようと考えています。

    ApplicationExitイベントハンドラというものを使えば、[×]をクリックしたときににそのイベントハンドラを起動させることが分かりその記述もできましたが、このイベントハンドラ(1)の場所に処理が飛んできた瞬間にアプリケーションで保持しているデータの一部がnull値に変更されてしまいます。(ウォッチで確認しました)
    アプリケーションで保持しているデータは配列で設定しており、boolやstring型があります。
    変更されるデータは、string型のTextデータのみであり、bool型の値は変更されずに保持されています。
    これは、visual c# 2010の仕様なのでしょうか。
    Text型のデータを保持させたまま保存するには、どのように対処すればよいか、ご教授よろしくお願いいたします。


    private void Form1_Load(object sender, EventArgs e)
        {
        //ApplicationExitイベントハンドラを追加
        Application.ApplicationExit += new EventHandler(Application_ApplicationExit);

        //フォームを起動したときの処理
    }


    //ApplicationExitイベントハンドラ
    private void Application_ApplicationExit(object sender, EventArgs e)
    { //(1)ここに処理が来た時にTextに設定している値がnullに変わってしまう

     //ここで、アプリケーションが保持している配列のデータをファイルに書き込みしたい

            //ApplicationExitイベントハンドラを削除
            Application.ApplicationExit -= new EventHandler(Application_ApplicationExit);

    }

    よろしくお願いいたします。

    2011年7月3日 3:42

回答

  • 正確ではないように感じます。
     

    確かにその通りですね。実は私も自信が無くて、それで「インスタンスは保障されていないと思われますので」というぼかした書き方になっており、この辺りの詳しい情報をお持ちの方がおられれば教えていただきたいと思っています。ApplicationExitイベントはどうやらメッセージループが全て終了した後に発生するようですが、ここまででどういう処理が終わっているのか少し調べてみたのですがわかりませんでした。そもそもフォームというのは誰からも参照されていなくてもGCの対象になりません。つまり、特殊な扱いをされているわけですが、そこからアプリケーション終了時にも特殊な扱いをされていると思い、フォームのインスタンスが保障されないのではないかと思いました。しかし、おっしゃる通り、この場合はApplicationクラスにイベント登録していますから、フォームのインスタンスは存在していそうですね。ご指摘ありがとうございます。

    (参考)
    誰も参照していないフォームは、何故 GC の対象にならないのか
    http://blogs.wankuma.com/shuujin/archive/2006/02/27/21562.aspx

    Closing イベントではなく、FormClosing イベントを使うようにしましょう。
    Closing イベントや Closed イベントは過去のもので、現状は FormClosing イベントや FormClosed イベントを使う必要があります。
    (単に書き間違いだと思いますが、念のため) 

     先にご紹介した、

    ApplicationContext クラス
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.applicationcontext(v=VS.100).aspx

    のサンプルコードがClosingイベントを使用していたので、うっかりClosingイベントと書いてしまいました。(どうもClosingイベントが未だにすっと体に入ってくるようです・・・)
    気付くべきでした。こちらもご指摘ありがとうございます。

    #というわけで上記のApplicationContextクラスのページにその指摘を書き込んどいた方がいいのかなぁと思ったりします。本家英語のサイトにも書かれていなかったので念のために確認してみましたが、ApplicationContextクラスでもFormClosingイベントは問題なく発生しました。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク hanahana87 2011年7月6日 13:37
    2011年7月4日 1:44
    モデレータ
  • >お教え頂いております「FormClosing イベント」について
    FormClosed Eventを利用してください。
    FormClosing Eventは主にFormを閉じて良いか否かを制御するEventです。

    [Form.FormClosed Event]
      http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosed.aspx
    You can use this event to perform tasks such as freeing resources used by the form and
    to save information entered in the form or to update its parent form.

     

    XでFromを閉じることはForm.Close Methodを呼ぶのと同意です。

    Form.Close MethodをMSDNで調べると、以下のように記述されています。

    [Form.Close Method]
      http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx
    When a form is closed, all resources created within the object are closed and the form is disposed.

    すでにTextBoxのHWNDは破棄されており、TextはそのHWNDから取得するようになっているため、本現象が発生しています。
    HWNDはWindow(From)やControlのWindows API上での実体です。
    HWNDについてもっと詳しく知りたいのでしたら、
    Windows APIによるCodingに挑戦されたほうが早いでしょうね。

    ではなぜCheckBox.Checked Propertyは取得できるのかというと、
    CheckBoxのHWNDとは別にCheckBoxのInstanceがCheckの状態を保持しているためです。

    ただし、Controlでどのような情報を保持しているかは、MSDNから読み取るのは困難ですので、
    これに頼った実装はしてはなりません。

     

    何れにせよ、FormClosed Eventで処理を行ってみてください。

    すでに答えは出ているのですから、実際に試してみて、挙動を比較し調べてみてください。

    • 回答としてマーク hanahana87 2011年7月6日 13:37
    2011年7月6日 11:06

すべての返信

  • >変更されるデータは、string型のTextデータのみであり、bool型の値は変更されずに保持されています。
    >これは、visual c# 2010の仕様なのでしょうか。
    まず、これらの変数がどのように処理されているか(どこで宣言してInstanceを生成し、どのように値の設定や後片付けしているか)を明らかにしましょう。
    そうしないと、状況が良く分からないですよ。

    >アプリケーションを[×]で終了させる直前
    いくつか機会があります。
    ApplicationExitもひとつの機会です
    現状のUI構成や仕様から、どの機会で処理を行うのか判断しましょう。

    例えば、MainFormをXで閉じるとApplicationが終了しますが、
    Applicationが終了する前にForm.OnFormClosing/Form.OnFormClosed Methodが呼ばれます。
    また、それぞれに対応したEvent(Delegate)が呼ばれます。

    もし保存するデータがそのFormにのみ存在するならば、
    Form.OnFormClosed MethodやForm.FormClosed Eventで処理するのも方法のひとつです。

    まずは先に書いた状況を明らかにしましょう。


    • 編集済み kozz 2011年7月3日 4:24 Formが抜けていた
    2011年7月3日 4:11
  • ApplicationExitイベントハンドラというものを使えば、[×]をクリックしたときににそのイベントハンドラを起動させることが分かりその記述もできましたが、このイベントハンドラ(1)の場所に処理が飛んできた瞬間にアプリケーションで保持しているデータの一部がnull値に変更されてしまいます。(ウォッチで確認しました)

    ApplicationExit イベントでは遅すぎませんか?
    たぶん、メインフォームと言うべきフォームの FormClosing, FormClosed, Dispose などが呼び出された後なので、フォーム自体がすでになくなっています。
    この状態であなたが保存しようとしているデータはきちんと保持されているのですか?
    (Dispose で消していたりしませんか?)

    変更されるデータは、string型のTextデータのみであり、bool型の値は変更されずに保持されています。
    これは、visual c# 2010の仕様なのでしょうか。

    .NET Framework の仕様かそうでないかで言えば、今の情報だけでは何ともいえません。
    string 型のデータが FormClosing/FormClosed/Dispose あたりのいずれかで null にするというコードが書かれていれば、あなたのアプリケーションの実装仕様でしょう。
    TextBox.Text あたりの場合は、.NET Framework の仕様かもしれませんが、この場合はたぶん ObjectDisposedException がでたような気がします。

    # Visual C# 2010 の仕様と表現するとすれば、文法とか、書き方とかそういったコンパイラレベルの話ぐらいです。
    # ほかは、.NET Framework 4 の仕様とかに近いですね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年7月3日 8:29
    モデレータ
  • 皆さまコメントいただきましてありがとうございます。
    私はまだまだC#を始めたばかりで、「作って慣れる」ような感じでコードを書いています。
    文法にしても基本ができているとはいい難く、こちらのHPで質問ばかりするのも申し訳ないと感じていますが、もうすこしご教授お願いします。

    さて、該当のプログラムですが、フォーム内の別のボタンでも同じようにアプリケーションが保持しているデータをテキストファイルに保存するようにしていますが、こちらでは希望通りに書き出しができています。そのほかに、保持しているデータを消すような操作はしていないと思います。
    なお、FormClosing/FormClosed/Dispose のコードは記述しておりません。

    あわせて、プログラムを[×]で終了させる前の、
    Form.OnFormClosed MethodやForm.FormClosed Event
    FormClosing/FormClosed/Dispose
    ObjectDisposedException
    について、もう少し詳しく教えてください。

    変数の宣言及びプログラムの大きな流れは以下のとおりです。

    public partial class Form1 : Form
        {
            public struct alarm
            {

            //ここで構造体の宣言

            }

            public alarm[] alarmdata;
          
            //ここから、配列の宣言(以下は例)
    CheckBox[] EnabledBoxArray;
            CheckBox[] verydayBoxArray;
            DateTimePicker[] DatePickerBoxArray;

            ComboBox[] HHBoxArray;
            ComboBox[] MMBoxArray;
            public TextBox[] MessageBoxArray;
            TextBox[] SoundFilenameBoxArray;

           public Form1()
            {
                InitializeComponent();
             }

            private void Form1_Load(object sender, EventArgs e)
            {
       //フォームを起動したときの処理(テキストファイルからの設定データの読込み)
            }

            private void Application_ApplicationExit(object sender, EventArgs e)
            {
            //[×]をクリックしたときの処理

            }

            //以下、プログラムの各種処理
            //フォーム上のチェックボックスやテキスト等のコントロールに値を設定したりして時間になったらアラームを鳴らすプログラム

           //ボタンをクリックしたときに、設定データをファイルに書く操作もここに記述している

         }


    よろしくお願いします。

    2011年7月3日 13:40
  • さて、該当のプログラムですが、フォーム内の別のボタンでも同じようにアプリケーションが保持しているデータをテキストファイルに保存するようにしていますが、こちらでは希望通りに書き出しができています。そのほかに、保持しているデータを消すような操作はしていないと思います。

    自分でやっていないつもりでも、結果的になってしまうことはありますよ。
    それは自動生成のコードであったり、.NET Framework(標準クラスライブラリ)の仕様・設計であったり、ほかのチームメンバーが実装したコードだったりしますが。

    あわせて、プログラムを[×]で終了させる前の、
    Form.OnFormClosed MethodやForm.FormClosed Event
    FormClosing/FormClosed/Dispose
    ObjectDisposedException
    について、もう少し詳しく教えてください。

    ご自身で言われているとおり、「質問しているばかりでは申し訳ないと感じる」のであれば、一度調べてみましょうよ。
    それでわからなかったところを聞いていただいた方がむしろ早く済むと思いますよ。

    ・ObjectDisposedException は終了時と直接関係しません。
    ・OnFormClosing メソッドと FormClosing イベントはほぼ同等です。(イベントとメソッドのオーバーライド)
    ・OnFormClosed メソッドと FormClosed イベントはほぼ同等です。(イベントとメソッドのオーバーライド)

    //ここから、配列の宣言(以下は例)

    例と言われている割には string 型や bool 型が全く出てきていません。
    ソースコードそのものを出せというつもりはありませんが、実態に近いコードを提示する、あるいは再現可能なコードを提示するようにしてください。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年7月3日 15:28
    モデレータ
  • Azuleanさま

    コメントありがとうございます。

    お教えいただきましたキーワードを元に、調べてみることにします。

    また、進展がありましたら、実態に近いコードとともにこちらに質問させていただきます。

    そのときには、ご指導よろしくおねがいいたします。

    皆さまのように、プログラムが書けるようがんばってみます。

    2011年7月3日 15:47
  • 掲載されたコードを見ると、アプリケーションで保持している配列はフォームクラスに保持されているようです。ApplicationExitイベントの段階ではこのフォームクラスのインスタンスは保障されていないと思われますので、希望する配列の値が取得できないのでしょう。以下を参考にして、フォームのClosingイベントでその配列を受け取り、そこでファイルに書き出されてみてはいかがでしょうか?

    ApplicationContext クラス
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.applicationcontext(v=VS.100).aspx


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年7月3日 16:04
    モデレータ
  • 揚げ足気味ですが。

    ApplicationExitイベントの段階ではこのフォームクラスのインスタンスは保障されていないと思われますので、希望する配列の値が取得できないのでしょう。

    正確ではないように感じます。

    タイミングとしては Dispose されていますので、フォームに貼り付けられていたコントロールなどは使用できない状態になります。
    しかし、Application クラスにイベントを登録していることから、参照は存在しますので、自分で作った配列は保持できることになります。(それでも、あまりよい形ではありませんね)
    もっとも、フォームに貼り付けられているコントロール(TextBox など)の参照をまとめた配列の場合、Dispose された後の保障はありませんが…。

    このあたりの話をするならば、ガベージコレクションや Dispose の仕組み・考え方を身につけてもらわないといけませんので、あえて省略されたのかもしれませんね。

    以下を参考にして、フォームのClosingイベントでその配列を受け取り、そこでファイルに書き出されてみてはいかがでしょうか?

    Closing イベントではなく、FormClosing イベントを使うようにしましょう。
    Closing イベントや Closed イベントは過去のもので、現状は FormClosing イベントや FormClosed イベントを使う必要があります。
    (単に書き間違いだと思いますが、念のため)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年7月3日 22:29
    モデレータ
  • また、進展がありましたら、実態に近いコードとともにこちらに質問させていただきます。

    アドバイスをするならば、新しいプロジェクトを作ってみて、問題を起こすために必要と思われるコードだけコピペして、問題が起きるかどうかみることです。

    問題が起きるなら、そのプロジェクトに持って行ったコードの中に問題があるので、現実に問題が起きているプロジェクトよりも少ないコードで調査すれば済みます。あるいは、最小限のプロジェクトになってきているので、名前とか定数を変えて、質問に添えるとよいかもしれません。

    逆に問題が起きないなら、自分が思っていた部分では問題を再現できないことになります。
    問題を再現させるために必要なコードはほかにもあるはずなので、調べる範囲を広げてください。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年7月3日 22:32
    モデレータ
  • 正確ではないように感じます。
     

    確かにその通りですね。実は私も自信が無くて、それで「インスタンスは保障されていないと思われますので」というぼかした書き方になっており、この辺りの詳しい情報をお持ちの方がおられれば教えていただきたいと思っています。ApplicationExitイベントはどうやらメッセージループが全て終了した後に発生するようですが、ここまででどういう処理が終わっているのか少し調べてみたのですがわかりませんでした。そもそもフォームというのは誰からも参照されていなくてもGCの対象になりません。つまり、特殊な扱いをされているわけですが、そこからアプリケーション終了時にも特殊な扱いをされていると思い、フォームのインスタンスが保障されないのではないかと思いました。しかし、おっしゃる通り、この場合はApplicationクラスにイベント登録していますから、フォームのインスタンスは存在していそうですね。ご指摘ありがとうございます。

    (参考)
    誰も参照していないフォームは、何故 GC の対象にならないのか
    http://blogs.wankuma.com/shuujin/archive/2006/02/27/21562.aspx

    Closing イベントではなく、FormClosing イベントを使うようにしましょう。
    Closing イベントや Closed イベントは過去のもので、現状は FormClosing イベントや FormClosed イベントを使う必要があります。
    (単に書き間違いだと思いますが、念のため) 

     先にご紹介した、

    ApplicationContext クラス
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.applicationcontext(v=VS.100).aspx

    のサンプルコードがClosingイベントを使用していたので、うっかりClosingイベントと書いてしまいました。(どうもClosingイベントが未だにすっと体に入ってくるようです・・・)
    気付くべきでした。こちらもご指摘ありがとうございます。

    #というわけで上記のApplicationContextクラスのページにその指摘を書き込んどいた方がいいのかなぁと思ったりします。本家英語のサイトにも書かれていなかったので念のために確認してみましたが、ApplicationContextクラスでもFormClosingイベントは問題なく発生しました。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク hanahana87 2011年7月6日 13:37
    2011年7月4日 1:44
    モデレータ
  • みなさま

    コメント並びにご指導ありがとうございます。

    ヒントになるキーワードや、参考のHPについて紹介していただきまして大変助かります。

    内容的に私にとりましては、とても難しいものとなっておりますので、少し時間をかけて解析とプログラムの作成を行ってみたいと思います。

    そして、ある程度見えてきましたら、またこちらの場所で報告(になればいいですが)か、質問をさせていただきます。

    すこし、時間を頂きたたく皆様にはよろしくお願いいたします。

     

    2011年7月4日 8:21
  • 以下にSampleがありますよ。

    [Save and restore the state of a Windows Form in .NET 2.0]
      http://www.codeproject.com/KB/miscctrl/FormState.aspx?msg=1629302 
      .NET 2.0になっていますが、問題ありません。

    [Application Event Handler for WinForms]
      http://www.codeproject.com/KB/vb/aeh.aspx
      Eventの仕組みです。
      言語はVBですが、書き方が異なるだけで、仕組みはC#と同じです。

    [Beginning C# - Chapter 13: Using Windows Form Controls]
      http://www.codeproject.com/KB/books/1861004982.aspx
      FormやControl全般の説明です。おすすめです。

    2011年7月4日 12:33
  • お世話になります。
    実現可能なコードで事象を再現できましたのでこちらに記載させていただきます。
    お教え頂いております「FormClosing イベント」についてはまだ勉強できておりませんが、以下についてご確認いただきコメントいただければ幸いです。

    フォームには、checkBox1,label1,textBox1,checkBox2,label2,textBox2 があり配列を設定しています。
    また、ボタンが1個あり、クリックすると上記配列の内容を、F:\CloseTest.csvのファイルの書き出すことができています。
    [×]をクリックすると、同様に F:\CloseTest.csvのファイルの書き出すようにしていますが、checkBox と labelの内容は書き出しできますが、textBoxの内容は書き出しできません。

    プログラムのコードは以下のとおりです。皆さまよろしくお願いします。


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Media;
    using System.IO;

    namespace クローズ
    {
        public partial class Form1 : Form
        {
            int maxindex = 2;

            CheckBox[] checkBoxArray;
            Label[] labelBoxArray;
            TextBox[] textBoxArray;


            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                //ApplicationExitイベントハンドラを追加
                Application.ApplicationExit += new EventHandler(Application_ApplicationExit);


                checkBoxArray = (CheckBox[])GetControlArrayByName(this, "checkBox");
                labelBoxArray = (Label[])GetControlArrayByName(this, "label");
                textBoxArray = (TextBox[])GetControlArrayByName(this, "textBox");

                string fileName = @"F:\CloseTest.csv";

                if (System.IO.File.Exists(fileName))
                {
                    Microsoft.VisualBasic.FileIO.TextFieldParser txtParser =
                                new Microsoft.VisualBasic.FileIO.TextFieldParser(
                                fileName,
                                System.Text.Encoding.GetEncoding("shift_jis"));

                    //内容は区切り文字形式
                    txtParser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
                    //デリミタはカンマ
                    txtParser.SetDelimiters(",");

                    for (int i = 0; i < maxindex; i++)
                    {
                        //一行を読み込んで配列に結果を受け取る
                        string[] splittedResult = txtParser.ReadFields();
                        checkBoxArray[i].Checked = Convert.ToBoolean(splittedResult[0].ToLower());
                        labelBoxArray[i].Text = splittedResult[1];
                        textBoxArray[i].Text = splittedResult[2];
                    }
                    //閉じる
                    txtParser.Close();
                }
            }

            //ApplicationExitイベントハンドラ
            //ここに、アプリケーションを[×]で終了した場合の、設定データを保存する処理を記述しようとしたが
            //Textデータが初期化されてしまい値を取得することができない。???
            private void Application_ApplicationExit(object sender, EventArgs e)
            {
                if (checkBox1.Checked == true)
                {
                    label1.Text = "チェックボックス1はチェック状態です";
                }
                else
                {
                    label1.Text = "";
                }

                if (checkBox2.Checked == true)
                {
                    label2.Text = "チェックボックス2はチェック状態です";
                }
                else
                {
                    label2.Text = "";
                }

                FileWrite();
                MessageBox.Show("アプリケーションが終了されます。");
                //ApplicationExitイベントハンドラを削除
                Application.ApplicationExit -= new EventHandler(Application_ApplicationExit);
            }
     
           
           
           
            private void button1_Click(object sender, EventArgs e)
            {
                if (checkBox1.Checked == true)
                {
                    label1.Text = "チェックボックス1はチェック状態です";
                }
                else
                {
                    label1.Text = "";
                }

                if (checkBox2.Checked == true)
                {
                    label2.Text = "チェックボックス2はチェック状態です";
                }
                else
                {
                    label2.Text = "";
                }

                FileWrite();
            }

            public void FileWrite()
            {
                StreamWriter sw = new System.IO.StreamWriter(@"F:\CloseTest.csv", false, System.Text.Encoding.GetEncoding("shift_jis"));
                for (int i = 0; i < maxindex; i++)
                {
                    sw.Write(checkBoxArray[i].Checked + ",");
                    sw.Write(labelBoxArray[i].Text + ",");
                    sw.Write(textBoxArray[i].Text + "\n");
                }
                sw.Close();
            }


            public object GetControlArrayByName(Form frm, string name)
            {
                System.Collections.ArrayList ctrs =
                    new System.Collections.ArrayList();
                object obj;
                for (int i = 1;
                    (obj = FindControlByFieldName(frm, name + i.ToString())) != null;
                    i++)
                    ctrs.Add(obj);
                if (ctrs.Count == 0)
                    return null;
                else
                    return ctrs.ToArray(ctrs[0].GetType());
            }

            public static object FindControlByFieldName(Form frm, string name)
            {
                System.Type t = frm.GetType();

                System.Reflection.FieldInfo fi = t.GetField(
                    name,
                    System.Reflection.BindingFlags.Public |
                    System.Reflection.BindingFlags.NonPublic |
                    System.Reflection.BindingFlags.Instance |
                    System.Reflection.BindingFlags.DeclaredOnly);

                if (fi == null)
                    return null;

                return fi.GetValue(frm);
            }
        }
    }

    2011年7月5日 14:25
  • 確かにApplicationExitでブレークポイントはるとTextBoxの値だけがなくなっていますね。
    私にはなぜだかわかりませんが、結局内容は保証されないんじゃないかと思います。
    なので、やっぱりFormClosingイベントでやったほうがいいんじゃないでしょうか。
    ApplicationExitイベントじゃないとだめな理由があれば、それを書いたほうが解決しやすいと思います。
    2011年7月6日 5:29
  • みなさん書かれてますが、Application_Exitではフォームが閉じた後ですので、TextBox以外で読み取れたのがたまたまなだけで、元々正常に読み取れる保証はありません。
    皆さんのアドバイスどおり、FormClosingやFormClosedなどを使用しましょう。

    ObjectDisposedExceptionにならないのは、おそらくCloseされただけでまだDisposeはされてない状態であるとか、そういうようなことじゃないかと思います(未確認)。
    あるいは、破棄はされているがたまたまチェックを素通りするコードパスになっているか。

    2011年7月6日 8:32
  • >お教え頂いております「FormClosing イベント」について
    FormClosed Eventを利用してください。
    FormClosing Eventは主にFormを閉じて良いか否かを制御するEventです。

    [Form.FormClosed Event]
      http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosed.aspx
    You can use this event to perform tasks such as freeing resources used by the form and
    to save information entered in the form or to update its parent form.

     

    XでFromを閉じることはForm.Close Methodを呼ぶのと同意です。

    Form.Close MethodをMSDNで調べると、以下のように記述されています。

    [Form.Close Method]
      http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx
    When a form is closed, all resources created within the object are closed and the form is disposed.

    すでにTextBoxのHWNDは破棄されており、TextはそのHWNDから取得するようになっているため、本現象が発生しています。
    HWNDはWindow(From)やControlのWindows API上での実体です。
    HWNDについてもっと詳しく知りたいのでしたら、
    Windows APIによるCodingに挑戦されたほうが早いでしょうね。

    ではなぜCheckBox.Checked Propertyは取得できるのかというと、
    CheckBoxのHWNDとは別にCheckBoxのInstanceがCheckの状態を保持しているためです。

    ただし、Controlでどのような情報を保持しているかは、MSDNから読み取るのは困難ですので、
    これに頼った実装はしてはなりません。

     

    何れにせよ、FormClosed Eventで処理を行ってみてください。

    すでに答えは出ているのですから、実際に試してみて、挙動を比較し調べてみてください。

    • 回答としてマーク hanahana87 2011年7月6日 13:37
    2011年7月6日 11:06
  • 皆さま

    たくさんのコメントご指導ありがとうございました。

    お教えいただきました下記リンクのサンプルの応用により、実現したい動作のプログラムができるのではないかと考えています。

    先の事象を確認したプログラムに、FormClosed Event を適用して作成してみたいと思います。

    どの部分を、切り貼りするのかも戸惑うところですが頑張ってみます。

    本当にありがとうございました。

     

    ApplicationContext クラス
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.applicationcontext(v=VS.100).aspx

    2011年7月6日 13:36