.NET の Timer を考えよう(2)


Timer の話を続けましょう。その1を読んでいない方は先にこちらを。

MainWindow.xaml.cs を読む

Abhishek Sur さんの TimersDemo です。WPF なので、XMAL で書かれています。要するに、XMLです。UI 自体は XAML ではあるけど、VS2010 では GUI 操作できるので従来の .NET プログラミングとほとんど同じ。たとえば、ボタンを置いてそれをダブルクリックすると、C# の button_Click(…) のような関数が定義されて、中身を書くわけです。

MainWindow.xaml.cs (一部省略)を見てみましょう。

namespace TimersDemo
{
	///
	/// Interaction logic for MainWindow.xaml
	///
	public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();
			this.Dispatcher.Thread.Name = "UI THREAD";
		}

		# region System.Windows.Forms.Timer

		private System.Windows.Forms.Timer WinTimer = new System.Windows.Forms.Timer();
		ObservableCollection WinTimerList = new ObservableCollection();
		private void btnwft_Click(object sender, RoutedEventArgs e)
		{
			this.WinTimer.Interval = 1000; //1 sec
			this.WinTimer.Tick += new EventHandler(WinTimer_Tick);
			this.WinTimer.Start();
			this.WinTimerList.Clear();
			this.lstwft.DataContext = this.WinTimerList;
		}

		void WinTimer_Tick(object sender, EventArgs e)
		{
			this.WinTimerList.Add(string.Format("Tick Generated from {0}", Thread.CurrentThread.Name));
		}

		# endregion

		# region System.Timers.Timer
		// 中略
		# endregion

		# region System.Threading.Timer
		// 中略
		# endregion

		private void btnSleep_Click(object sender, RoutedEventArgs e)
		{
			Thread.Sleep(5000);
		}

		# region Dispatcher
		// 中略
		# endregion
	}
}

ObservableCollection とは?

ちょっと横道にそれますが、ObservableCollection という型が出てきますね。この ObservableCollection、基本は System.Collections.ObjectModel.Collection と同じ。クラスの動的な配列を扱うときの Collection 型から派生しています。違いは、名前から想像できるように「可観測コレクション」つまりコレクションへの追加や削除といった「変化」を CollectionChanged イベントで捕捉できる仕組みが追加されているのです。

このクラスを使うことで、ListBox のアイテムと結び付けているわけです。

this.lstwft.DataContext = this.WinTimerList;

うまくできてますね。lstwft は LiSTbox Windows Form Timer の大文字だけをとった命名規則ですかね。

TimersDemo の動作

まず、System.Windows.Forms.Timer からみましょう。ボタンClick関数は、次のようになっています。

private void btnwft_Click(object sender, RoutedEventArgs e)
{
	this.WinTimer.Interval = 1000; //1 sec
	this.WinTimer.Tick += new EventHandler(WinTimer_Tick);
	this.WinTimer.Start();
	this.WinTimerList.Clear();
	this.lstwft.DataContext = this.WinTimerList;
}

タイマー間隔を1秒にしてイベントハンドラを設定し、タイマーを走らせて、ListBoxをクリア、そしてイベントで出力する ObservableCollection 型をListBoxとバインドしています。

void WinTimer_Tick(object sender, EventArgs e)
{
	this.WinTimerList.Add(string.Format("Tick Generated from {0}", Thread.CurrentThread.Name));
}

イベントハンドラは、このようにただ ListBox にメッセージを出すだけです。これじゃあ、動かしてるだけやん!ということで、Sleep というボタンが気になります。

private void btnSleep_Click(object sender, RoutedEventArgs e)
{
	Thread.Sleep(5000);
}

スレッドを5秒間止めてますね。タイマーがこの影響をどう受けるかを確かめようという趣向のようですので、それぞれ1つのタイマーを動かしながら動作を注視します。

timer4

すると、System.Windows.Forms.Timer と DispatcherTimer は、Sleep している間は動作してないように見えます。対して System.Timers.Timer、System.Threading.Timer は Sleep が終わるとまとめてそのぶんのメッセージが出ます。

これは、タイマの処理自体は Sleep 中も行われていて、あとでまとめてメッセージが表示されているか、あるいは、タイマ処理の要求がすべて保留されていて、一気に処理しているかのどちらかと考えられます。それがどちらかを知るためには、処理の時刻を知りたいですよね。

でも長くなったので、それはその3に。

clock.NET の Timer を考えよう |2|

 

(参考)

(注)

印刷
You can skip to the end and leave a response. Pinging is currently not allowed.
Subscribe to RSS Feed Twitter は Ume108 だよ