- PR -

VB.NET によるイベント ハンドラのについて

投稿者投稿内容
Yun
会議室デビュー日: 2004/02/10
投稿数: 13
投稿日時: 2004-02-12 14:46
みなさん、ありがとうございます。

昔使っていたHPに実際のソースをUPしました。
動かない方はこちらを使ってみて下さい。
作成環境は
Framework1.1 Ver1.1.4322
Microsoft Development Environment 2003 Ver7.1.3091
です。

URL
http://www.geocities.co.jp/AnimeComic/7725/Sample.lzh
ナキヲ
常連さん
会議室デビュー日: 2003/08/22
投稿数: 32
お住まい・勤務地: 京都・自宅から勤務地まで自転車で40分
投稿日時: 2004-02-12 14:50
そんなとこはないだろうと思ってやってみたら、
なりますね(^^;
VBは苦手なのでC#で、、

"Sample1実行!!!!!"の前の
timer1.Interval = 100;
を消したらTimerは生きつづけるようです。
なぜこんな挙動をするのかは。。。よくわからないです。

コード:
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Timer timer1;
		private System.Windows.Forms.Button button1;
		private System.ComponentModel.IContainer components;

		public Form1()
		{
			InitializeComponent();
		}

		protected override void Dispose( bool disposing )
		{
			// 省略
		}

		#region Windows フォーム デザイナで生成されたコード 
			// 省略
		#endregion

		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void timer1_Tick(object sender, System.EventArgs e)
		{
			System.Diagnostics.Debug.WriteLine("Form1.timer1_Tick");
		}

		private void Form1_Load(object sender, System.EventArgs e)
		{
			timer1.Enabled = true;
			timer1.Interval = 1000;
			timer1.Start();
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			clsSample clsTest = new clsSample();
			clsTest.evtEvent += new EventHandler(Sample1);
			clsTest.Aciton();
		}

		private void Sample1(object sender, EventArgs e)
		{
			timer1.Interval = 100;
			System.Diagnostics.Debug.WriteLine("Sample1実行!!!!!");
		}
	}
	
	public class clsSample
	{
		public event EventHandler evtEvent;
		protected System.Diagnostics.Process SampleProcess = new System.Diagnostics.Process();

		public clsSample()
		{
			SampleProcess.EnableRaisingEvents = true;
			SampleProcess.Exited += new EventHandler(processExited);
		}

		public void Aciton()
		{
			SampleProcess.StartInfo.FileName = @"c:\test.txt";
			SampleProcess.Start();
		}

		private void processExited(object sender, EventArgs e)
		{
			if(evtEvent != null)
				evtEvent(this, EventArgs.Empty);
		}
	}

りばぁ
大ベテラン
会議室デビュー日: 2003/11/26
投稿数: 130
お住まい・勤務地: 愛知県
投稿日時: 2004-02-12 15:06
勘ですけど。

タイマーを起動したままIntervalの値を変更してはダメなのでは?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-12 15:13
引用:

りばぁさんの書き込み (2004-02-12 14:29) より:

VB6ですと、WithEvents(WidthEventsではないですよw)宣言の方法しかありませんが、
.NETはいくつかやり方があるようですね。


 あ、いや、「AddHandlerができなかった」のですが、この記述ですと、「できない」とは書いていないですよね。。。

[修正]
 タイマー起動中のインターバル変更は、「変更したときからカウントされなおします」と書いてあります。
[修正後]
 System.Timers.Intervalについては、
引用:

Timer が開始した後に間隔を設定すると、カウントがリセットされます。たとえば、間隔を 5 秒に設定し、 Enabled を true に設定した場合は、 Enabled を設定した時刻からカウントが開始します。カウントが 3 秒のときに間隔を 10 秒にリセットした場合、最初の Elapsed イベントは Enabled を true に設定してから 13 秒後に発生します。


とあります。このことから、カウント中に変更すると、変更した時点でカウントがリセットされるが、Elapsedは発生すると理解できます。

 しかし、System.Windows.Forms.Timerについては、このような記述がありません。
[/修正]



#####
なっくさん
 割り込んでごめんなさいね。

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-02-12 15:41 ]
ナキヲ
常連さん
会議室デビュー日: 2003/08/22
投稿数: 32
お住まい・勤務地: 京都・自宅から勤務地まで自転車で40分
投稿日時: 2004-02-12 15:16
引用:

タイマーを起動したままIntervalの値を変更してはダメなのでは?



それ、思ったんですけど、例えば
最初に動いている状態のtickイベント内で、
コード:
		private void timer1_Tick(object sender, System.EventArgs e)
		{
			System.Diagnostics.Debug.WriteLine("Form1.timer1_Tick");
			timer1.Interval = timer1.Interval+10;
		}



みたいにintervalを書き換えてもtimerは止まらないようです。
Timerのドキュメントにもそれらしきことは書いてないので、
何か他の要因があるのではないかと思います
Yun
会議室デビュー日: 2004/02/10
投稿数: 13
投稿日時: 2004-02-12 15:22
ナキヲ様、C#にて検証ありがとうございます。
自分の環境や言語ではないと分かっただけでも助かります。><

りばぁ様
ボタンを追加して変更してみました。
結果はタイマー実行中に変更可能でした。
コード:

    Private Sub Button2_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button2.Click
        Timer1.Interval = 1000
    End Sub



こんな感じで。
やってることはButton2と同じ「はず」なのですが・・・
ほんと、何でイベントが起きなくなるのでしょう?何故です^^;
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-02-12 15:25
一回タイマー止めてから再起動でいいのではないでしょうか?
個人的にはタイマーイベントの処理をしている間はタイマーを止めておいたほうがいいと
思いますし
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-02-12 15:24
引用:

Timerのドキュメントにもそれらしきことは書いてないので、
何か他の要因があるのではないかと思います


あんまり見てなかったんですが…つまっているようなので…

原因は、プロセスのExitedイベントです(と思います)。
なぜかというと、うーん、コントロールはUIスレッド以外から操作してはならないという制限に引っかかるからです。

これを回避するには、ProcessのSynchronizingObjectにフォームのインスタンスをセットするか、イベントハンドラからフォームのInvokeを使用してタイマーを操作するか辺りになります。
# Exitedイベントは非同期に発生するため、SynchronizingObjectが設定されていない場合は、スレッドプールのスレッドで実行されます。

スキルアップ/キャリアアップ(JOB@IT)