技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

C#:await・asyncの簡単なサンプルコード

C#のawait・asyncは非同期処理のために用意された文法なのですが、Webで調べてみても難しく書かれていることが多く、そもそも何のための処理なのか理解するのが難しい感があります。
await・asyncを用いて関数を呼び出しても、その関数の処理が終わるまで待つという動きをするので、同期処理と何が違うのかいまいちわかりにくいというのもあると思います。
以上のような背景があるので、簡単なサンプルコードを書いてみることとしました。
 
await・asyncは、GUIアプリのために用意された文法と考えて良いです。
await・asyncを用いない場合、処理中はGUI操作ができなくなるのですが、await・asyncを用いて呼び出した関数を処理している間はGUI操作が可能になります。
GUI操作と並行で処理ができる、という意味で、await・asyncは非同期処理であると言えます。
 
以下、Windows Formのサンプルコードです。
3秒後にボタン押下時のシステム時刻をラベルに表示するというサンプルコードであり、await・asyncを用いたボタンとそうではないボタンを用意して挙動の違いを確認します。
 
【サンプルコード】
・From1.cs(デザイン)
f:id:akira2kun:20200531215528j:plain
 
・Form1.cs(ビジネスロジック
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncAwaitTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Asyncボタン
        private async void button1_Click(object sender, EventArgs e)
        {
            String date = await AsyncProc();
            label1.Text = date;
        }

        private async Task<String> AsyncProc()
        {
            DateTime dt = DateTime.Now;
            await Task.Delay(3000);
            return dt.ToString();
        }

        // NoAsyncボタン
        private void button2_Click(object sender, EventArgs e)
        {
            String date = NoAsyncProc();
            label2.Text = date;
        }

        private String NoAsyncProc()
        {
            DateTime dt = DateTime.Now;
            Thread.Sleep(3000);
            return dt.ToString();
        }
    }
}
 
【実行結果】
・Asyncボタンを押してから1秒以内にNoAsyncボタンを押下
→Asyncボタンの処理中もNoAsyncボタンを押下可能であるため、2つのボタンに対応するラベルの表示上、時刻の差異は1秒以内です。
f:id:akira2kun:20200531215605j:plain

・NoAsyncボタンを押してから1秒以内にAsyncボタンを押下
→NoAsyncボタンの処理中はAsyncボタンを押下不可能であるため、2つのボタンに対応するラベルの表示上、時刻の差異は3秒以上となります。

f:id:akira2kun:20200531215635j:plain