【C#】async/awaitを利用したマルチスレッド実装テンプレート

ボタン押下時の処理にて、以下のような要件を想定したサンプルです。
(.NET Framework4.5.1利用)

開始

A処理
↓   ↓
B処理  C処理 ※
↓   ↓
D処理

終了

※ここだけ並行処理可能なので、マルチスレッド化したい。

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

namespace AsyncSample
{
    /// <summary>
    /// async/awaitの利用サンプル
    /// </summary>
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// ボタン押下時に並行実行可能な処理をマルチスレッドで実行する
        /// ※private void → private async void に変更
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button1_Click(object sender, EventArgs e)
        {
            Console.WriteLine("最初に行う処理。これが終わるまではMainSampleは呼び出されない。");

            //マルチスレッド処理(awaitを付けて、メソッド内の処理が終わるのを待っている)
            await MainSample();

            Console.WriteLine("最後に行う処理。MainSampleが終わった後に呼び出される。");
        }

        /// <summary>
        /// 並行実行可能な処理
        /// ※private void → private async Task に変更
        /// </summary>
        /// <returns></returns>
        private async Task MainSample()
        {
            //task1の実行を開始
            Task<string> task1 = Dummy(5, "task1");

            //task2の実行を開始
            Task<string> task2 = Dummy(1, "task2");

            //task1とtask2の実行が終わるまで待つ
            await task1;
            await task2;

            //それぞれのtaskの戻り値を取得
            Console.WriteLine("task1の戻り値:" + task1.Result);
            Console.WriteLine("task2の戻り値:" + task2.Result);
        }
        
        /// <summary>
        /// 複数の引数を受け取り、処理結果を戻り値として返す
        /// ※private void → private async Task<string> に変更。戻り値が不要の場合は、private async Task にする。
        /// </summary>
        /// <param name="i"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        private async Task<string> Dummy(int i, string s)
        {
            Console.WriteLine("処理開始:" + i);

            string dummyText = await Task.Run(() =>
            {
                //何らかの重い処理・・・
                System.Threading.Thread.Sleep(1000 * i);
                return s + "の処理完了:" + DateTime.Now.ToString();
            });

            Console.WriteLine("処理完了:" + i);

            return dummyText;
        }
    }
}

実行結果>

最初に行う処理。これが終わるまではMainSampleは呼び出されない。
処理開始:5
処理開始:1
処理完了:1
処理完了:5
task1の戻り値:task1の処理完了:2017/02/18 0:15:32
task2の戻り値:task2の処理完了:2017/02/18 0:15:28
最後に行う処理。MainSampleが終わった後に呼び出される。

動作可能なサンプルを作成しました。こちらから購入できます

C#のマルチスレッドのサンプルアプリを提供します (応答なし)になったり、表示が更新されなくて困っている時に!