あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

【C#】Windowsフォーム アプリケーションでDispatcherTimerを利用する

 今回はWindowsフォーム アプリケーションでThreading.DispatcherTimerを使用してみます。
 Windows.Forms.Timerはスレッドセーフではありますが、WindowメッセージのWM_TIMERで処理されるため遅いという欠点があります。
 その点、DispatcherTimerはスレッドセーフかつ、UIスレッド内での動作が基本となっており、Forms.Timerを使うくらいならThreading.DispatcherTimerの使用を推奨します。
 WPFへ移行する際もそのまま利用できますし、Timers.TimerはWPFではサポートされていないため非常にお勧めです。

 フォームにラベルを配置し、ボタンを押すとテロップのように移動するサンプルとなっています。

デザイナー側実装

namespace DispatcherTimerSample
{
  partial class Form1
  {
    /// <summary>
    /// 必要なデザイナー変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

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

    /// <summary>
    /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
    /// コード エディターで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
      this.button1 = new System.Windows.Forms.Button();
      this.label1 = new System.Windows.Forms.Label();
      this.SuspendLayout();
      // 
      // button1
      // 
      this.button1.Location = new System.Drawing.Point(186, 12);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(86, 42);
      this.button1.TabIndex = 0;
      this.button1.Text = "移動開始";
      this.button1.UseVisualStyleBackColor = true;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      // 
      // label1
      // 
      this.label1.Font = new System.Drawing.Font("メイリオ", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128)));
      this.label1.Location = new System.Drawing.Point(169, 97);
      this.label1.Name = "label1";
      this.label1.Size = new System.Drawing.Size(116, 30);
      this.label1.TabIndex = 1;
      this.label1.Text = "移動する";
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(284, 262);
      this.Controls.Add(this.label1);
      this.Controls.Add(this.button1);
      this.Name = "Form1";
      this.Text = "Form1";
      this.Load += new System.EventHandler(this.Form1_Load);
      this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.Label label1;
  }
}

 

 Visual Studioのプロジェクトの「参照の追加」→「アセンブリ」→「フレームワーク」と選択してWindowsBaseへの参照を追加してください。

コードビハインド側実装

using System;
using System.Windows.Forms;
using System.Windows.Threading;

namespace DispatcherTimerSample
{
  public partial class Form1 : Form
  {
    #region メンバ変数
    /// <summary>
    /// 画面更新制御タイマー
    /// </summary>
    DispatcherTimer _DispatcherTimer = new DispatcherTimer();
    #endregion

    #region コンストラクタ
    /// <summary>
    /// クラスの新しいインスタンスを初期化します。
    /// </summary>
    public Form1()
    {
      InitializeComponent();
    }
    #endregion

    #region イベント
    /// <summary>
    /// フォームが初めて表示される直前に発生します。
    /// </summary>
    /// <param name="sender">イベント発生オブジェクト</param>
    /// <param name="e">イベント引数</param>
    private void Form1_Load(object sender, EventArgs e)
    {
      this._DispatcherTimer.Tick += LabelMoveDispatcherTimer_Tick;
    }

    /// <summary>
    /// ボタンコントロールがクリックされたときに発生します。
    /// </summary>
    /// <param name="sender">イベント発生オブジェクト</param>
    /// <param name="e">イベント引数</param>
    private void button1_Click(object sender, EventArgs e)
    {
      this._DispatcherTimer.Interval = TimeSpan.FromMilliseconds(100);
      this._DispatcherTimer.Start();
    }

    /// <summary>
    /// タイマーの間隔が経過したときに発生します。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void LabelMoveDispatcherTimer_Tick(object sender, EventArgs e)
    {
      if (this.label1.Left - 1  < -this.Left)
      {
        this.label1.Left = this.Width;
      }
      else
      {
        this.label1.Left -= 1;
      }
    }
    #endregion
  }
}

 わたしの担当時、今期はWindowsフォーム アプリケーションで色々とサンプルをご紹介してきましたが、まだまだ業務では使えるかな?という印象でした。
 来期もまた別のテーマで色々とナレッジを残せたらと思います。