none
VC++のフォームタイマについて、聞きたい問題が有ります。 RRS feed

  • 質問

  • 開発環境: Win7   VS2010   VC++  .NetFramework4.0

    Winフォームアプリを作っています。 フォームにタイマを貼り付けています。 フォームロードイベントでタイマを起動しています。 タイマイベントの中で、BlueTooth通信をしています。 一回通信すると通信相手のBluetoothアタプタのランプが一回点滅します。 先ほど、このフォームを閉じた後に(アプリを終了していません)、通信相手のランプまた点滅しています。 ということは、また通信しています。 え~、あのタイマまた生きています!確かに、タイマを終了させるコードを書いていませんでした。   でも、VB、C#の経験では、フォームを閉じると、そのフォームに貼り付けたタイマは、終了コードがなくても、自然に終了します。  VC++はそうではないですか?フォーム終了しても、フォームのタイマはまた生きているものですか?


    cyo




    • 編集済み AK46.5 2013年4月26日 7:28
    2013年4月26日 7:24

回答

  • プログラムは祈った通りに動作するのではなく、書かれた通りに動作します。またVB・C#・C++/CLIとも同じことを書けば同じ動作をします。閉じたときに終了するように書いたかどうかの違いだと思います。

    さらに言うと.NET Frameworkにはタイマーは3種類あるので漠然と「タイマ」と言われてもわかりません。

    • 回答としてマーク AK46.5 2013年4月27日 16:29
    2013年4月26日 8:23
  • ああ、対象のフォームを閉じて他のフォームが残っている、プロセスが普通に継続する状況なんですね。
    最初の質問からはわかりませんよ。

    さて、Timer が勝手に終了する仕組みは、Form のデザイナで貼り付けた際に、components という変数に登録しておくことで、Dispose メソッド(C++/CLI ではデストラクタ)で components が Dispose(C++/CLI では delete)されることで実現されています。
    あなたが Timer が残り続けると主張する以上は、その Form が Dispose(delete) されていないのでしょう。ShowDialog で表示したフォームは閉じても delete しなければ後始末されないので、ちゃんと delete してください。

    // あるいは、デストラクタのコードをあなたが消してしまったか。

    • 回答としてマーク AK46.5 2013年4月27日 16:29
    2013年4月27日 14:49
    モデレータ

すべての返信

  • プログラムは祈った通りに動作するのではなく、書かれた通りに動作します。またVB・C#・C++/CLIとも同じことを書けば同じ動作をします。閉じたときに終了するように書いたかどうかの違いだと思います。

    さらに言うと.NET Frameworkにはタイマーは3種類あるので漠然と「タイマ」と言われてもわかりません。

    • 回答としてマーク AK46.5 2013年4月27日 16:29
    2013年4月26日 8:23
  • タイマーが生きていると判断した根拠が「通信が継続しているから」だけなら、根拠としては乏しいのでは?
    アプリの終了操作をして、プロセスが終わらない状態でタイマーの Tick イベントにブレークポイントを設定してもこないなら、タイマーが原因説は否定されます。

    // 個人的には、その Bluetooth の通信ライブラリの終了処理とか解放処理とか書き忘れていることはないか?と疑いますが。ネイティブのスレッドが内部で作られて、動きっぱなしとかあり得そうなので。

    2013年4月26日 17:16
    モデレータ
  • お返事ありがとうございます。

    まず、フォームに貼り付けるタイマは System.Windows.Forms.Timer しかないと思います。 他のタイマはフォーム貼り付けることができないと思います。

    アプリが正常に終了すれば、タイマイベントは当然終了すると思います。 私が聞きたいことは、アプリを終了していない状態で、その中の一つのフォームを閉じたけど、閉じたフォームのタイマイベントはまだ生きているような状況は、VC++のアプリでは通常なことでしょうか。

    質問を投稿した後、フォーム終了イベント中で、timer1->Enable=false; を追記したことで、フォーム終了後、Bluetoothの通信がなくなりました。


    cyo

    2013年4月27日 13:24
  • ああ、対象のフォームを閉じて他のフォームが残っている、プロセスが普通に継続する状況なんですね。
    最初の質問からはわかりませんよ。

    さて、Timer が勝手に終了する仕組みは、Form のデザイナで貼り付けた際に、components という変数に登録しておくことで、Dispose メソッド(C++/CLI ではデストラクタ)で components が Dispose(C++/CLI では delete)されることで実現されています。
    あなたが Timer が残り続けると主張する以上は、その Form が Dispose(delete) されていないのでしょう。ShowDialog で表示したフォームは閉じても delete しなければ後始末されないので、ちゃんと delete してください。

    // あるいは、デストラクタのコードをあなたが消してしまったか。

    • 回答としてマーク AK46.5 2013年4月27日 16:29
    2013年4月27日 14:49
    モデレータ
  • Azuleanさん、ご返事ありがとうございます。

    Fromを閉じる時に、Dispose()メソッドを実行していませんでした。 VBのように、Close()メソッドでフォームを閉じました。これが原因でしょうか。  VC++やはり難しいですね。  

    また、私はデストラクタのコードを触っていません。 delete 検索してみました。下記のコードがありました。 

    public:
       form1(void)
      {
    	InitializeComponent();
    	//
    	//TODO: ここにコンストラクタ コードを追加します
    	//
      }
    
    protected:
     	/// <summary>
    	/// 使用中のリソースをすべてクリーンアップします。
    	/// </summary>
    	~form1()
    	{
    		if (components)
    		{
    			delete components;
    		}
    	}

    VC++でフォームアプリを作ると、フォームデザインコードがイベント処理のコードと同じファイルにおるのがちょっと不便ですね。


    cyo


    • 編集済み AK46.5 2013年4月27日 16:27
    2013年4月27日 16:25
  • Fromを閉じる時に、Dispose()メソッドを実行していませんでした。 VBのように、Close()メソッドでフォームを閉じました。これが原因でしょうか。  VC++やはり難しいですね。

    VB.NET だろうが、C# だろうが、Close するだけでは Dispose されません。(VB.NET/C#/C++ 問わず、ShowDialog なら同じ挙動になる)
    実際、タイマーが動き続ける事象は C# でも起きることを確認しています。

    起きないとすれば、Using(using) を使っていたか、モードレスだったんじゃないでしょうか。
    きちんと差を見極めて、正しい理解を身につけてください。今回のケースで言えば、Visual C++ 特有の事象と思い込まないようにしてください。

    VC++でフォームアプリを作ると、フォームデザインコードがイベント処理のコードと同じファイルにおるのがちょっと不便ですね。

    余談ですが、Visual C++ でフォームアプリケーションプロジェクトは、どちらかというと端っこです。
    実際、Visual C++ 2012 からは新規に作れませんので、そう言ったものだと頭の片隅にでも覚えておいてください。

    2013年4月27日 21:28
    モデレータ