株式会社シベスピ 従業員ブログ

シベスピの社員ブログ。技術・想い・経験沢山書いていきます!

【C#】YouAreAnIdiot【Windowsフォームアプリケーション入門】

御託

最近生まれて初めての胃腸炎をやりました。フラフラしながら吐いたのは大昔インフルエンザをやった時以来でしょうか。冷凍ささみのせいかと思いましたがそれなら食中毒だろという気もするので結局原因不明でした。

さて、このWindowsフォームアプリケーション入門では、毎回何かしらのアプリケーションを作りながらFormアプリケーションの作り方を学んでいくのが目的ですが、今回はFormの中でもよく使うけどちょっとややこしい動きをする「Timer」を使っていきます。懐かしのブラクラ「YouAreAnIdiot」モドキを作りながらやっていきましょう。

概要

Timer(System.Windows.Forms.Timer)は、一定時間ごとにイベントを繰り返し発生させるコンポーネントです。イベントにメソッドを割り付けることにより、一定時間ごとにメソッドを実行できるようになります。要は一定間隔で関数を繰り返し実行させることができます。

プログラム

おなじみプロジェクト作成後の画面になります。(デフォルトのウィンドウサイズが大きくなってましたがPCをWindows10にしたのが関係してるのでしょうか)


ウィンドウサイズを調整した後、「ツールボックス」から「Label」を選択してフォームに貼り付け、下記のプロパティを設定します。

プロパティ名 設定値 概要
Name lblFace 変数名になります。
AutoSize False ラベルのサイズを手動で調整可能にします。
BackColor White 背景色を白(#FFFFFF)にします。
Dock Fill ラベルをウィンドウ全体に引き伸ばします。
Font Wingdings, 128pt 絵文字用のフォントを使用します。
ForeColor Black 文字色を黒(#000000)にします。
Text JJJ 絵文字フォントの顔に相当する文字を指定します。
TextAlign MiddleCenter 文字を中央に表示します。


ツールボックス」から「Timer」を選択してフォームに貼り付けます。


デザイナの下部に「timer1」と表示されるので、下記のようにプロパティを設定します。

プロパティ名 設定値 概要
Enabled true タイマーの有効にします。
Interval 1000 タイマーを実行する間隔(ms)です。


デザイナの下部の「timer1」をダブルクリックするとコードエディタに移動し「timer1_Tick」関数が追記されるので、下記のようにコードを記載します。

private void timer1_Tick(object sender, EventArgs e)
{
    // メソッドを実行するたびに顔文字の色を反転させる
    if (lblFace.BackColor == Color.Black)
    {
        lblFace.BackColor = Color.White;
        lblFace.ForeColor = Color.Black;
    }
    else
    {
        lblFace.BackColor = Color.Black;
        lblFace.ForeColor = Color.White;
    }
}


実行すると次のような感じになります。

御託2

正直これだけだとTimerの利点があんまり見えないなと作ってから思いました。一定周期で最新の情報を取得したりするほうがよく使用されるでしょうか。いろいろ触ってみて便利な使い方を見つけて貰えば良いと思います。(丸投げ)
便利なTimerですが、実はこれに機能を盛り込みすぎるのも危険です。

Timerを使用する際の注意点

Windowsフォームアプリケーションは「イベントドリブン」、簡単に言うとボタンクリックなどのユーザー操作によって処理が行われる形式となっています。これによりイベント時(ボタンクリックなど)に実行される処理の時間が長いと、処理が終わるまでフォームがフリーズしてしまいます。
Timerもボタンクリックなどと同様にイベントを発生させ処理を実行しています。なのでTimerでも時間のかかる処理を行うと、その処理中はフォームがフリーズしてしまいます。

またTimerの動きは「処理が終わるたびに一定時間待機し、次の処理を実行する」のではなく、「一定間隔ごとにイベントを発生させる」です。つまりTimerで行っている処理が終わっているかどうかは関係なく、一定時間ごとにどんどん処理を実行します。これは「実行間隔 > 処理時間」の時は良いですが「実行間隔 < 処理時間」になると、処理が終了したあとすぐに次の処理が始まることとなり、フォームがフリーズし続けることになります。(スレッドを作成しているわけではないので、処理を実行中にまたその処理を実行するということにはなりません)
Timerに限った話ではないのですが、時間のかかる処理は別スレッドで実行(BackGroundWorkerやasync/await)するなど、フォームがフリーズしないように注意する必要があります。(マルチスレッド化は奥が深すぎるのでここでは触れません)

おわり

今回はTimer(System.Windows.Forms.Timer)を使用しました。便利さよりも厄介さがにじみ出る記事になっていますが、それだけドツボにはまりやすいコンポーネントということです。Windowsフォームアプリケーション初心者やプログラミング初心者は、スレッドやイベントの区別がついていなかったり、特に考えずコンポーネントを使用するのでなおさらです。
実はTimerにはいろいろな種類があり、それぞれメリットデメリットがあるのですが、それはFormアプリケーション入門以外の所でできればなと思います。

次回もFormでよく使うコンポーネントで何かしらを作っていきます。(つまり考えてない)