プレゼンテーションC#のasyncとawaitの使用


小さなコードを書いて、同僚にこの2つの文法糖のコードの実行順序を説明します.
class Program
    {
        static void Main()
        {
            Msg("Begin");
            DisplayValue();
            Msg("End");
            Console.Read();
        }

        #region async  
        public static async Task<double> GetValueAsync(double num1, double num2)
        {
            Msg("Into  GetValueAsync");
            var ret = await Task.Run(() =>
            {
                Msg("Into  GetValueAsync Task");
                for (int i = 0; i < 1000000; i++)
                    num1 = num1 / num2;
                Msg("out  GetValueAsync Task");
                return num1;
            });
            Msg("out  GetValueAsync");
            return ret;
        }
        public static async void DisplayValue()
        {
            Msg("Into  DisplayValue");
            var result = GetValueAsync(1234.5, 1.01);
            Msg("Middle  DisplayValue");
            Msg("Value is : " + await result);
            Msg("Out  DisplayValue");
        }
        #endregion

        private static int idx;
        static void Msg(string msg)
        {
            Interlocked.Increment(ref idx);
            var id = Thread.CurrentThread.ManagedThreadId.ToString();
            Console.WriteLine(idx.ToString() + ".  :" + id + "  " + msg);
            Thread.Sleep(100); //  cpu , 
        }
    }

コード実行結果:
1.  :1  Begin
2.  :1  Into  DisplayValue
3.  :1  Into  GetValueAsync
4.  :1  Middle  DisplayValue
5.  :3  Into  GetValueAsync Task
6.  :1  End
7.  :3  out  GetValueAsync Task
8.  :3  out  GetValueAsync
9.  :3  Value is : 2.47032822920623E-322
10.  :3  Out  DisplayValue

GetValueAsyncメソッドのasyncとawaitを削除

public static Task<double> GetValueAsync(double num1, double num2)
{
    Msg("Into  GetValueAsync");
    var ret = Task.Run(() =>
    {
        Msg("Into  GetValueAsync Task");
        for (int i = 0; i < 1000000; i++)
            num1 = num1 / num2;
        Msg("out  GetValueAsync Task");
        return num1;
    });
    Msg("out  GetValueAsync");
    return ret;
}

実行順序が変わり、次のようになります.
1.  :1  Begin
2.  :1  Into  DisplayValue
3.  :1  Into  GetValueAsync
4.  :1  out  GetValueAsync
5.  :3  Into  GetValueAsync Task
6.  :1  Middle  DisplayValue
7.  :1  End
8.  :3  out  GetValueAsync Task
9.  :3  Value is : 2.47032822920623E-322
10.  :3  Out  DisplayValue

分かったか?分からない場合は、上記のテストコードをあなたのプロジェクトにコピーして、変更して、実行してください.簡単にまとめてみましょう.-awaitコマンドスレッドを呼び出して非同期メソッドとメソッド内の後ろのコード-awaitコマンドを実行すると、現在のメソッドの後ろのコードがブロックされますが、外部呼び出しをブロックしません.-awaitはasyncと組み合わせて使用する必要がありますが、asyncは必ずしもawaitを必要としません.