首页 > 技术文章 > C#异步编程学习笔记之-async和await(续)

zhaow 2018-08-17 15:32 原文

书接上文,本篇主要记录的内容要点:
1、针对async和await在实际应用中的使用方式;
2、异步方法返回值(有返回值和无返回值)的两种情况;

示例一(无返回值):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "--主方法开始执行");
            TestAsync();
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "--主方法执行完毕!");
            Console.ReadKey();
        }

        static async void TestAsync()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "TestAsync方法开始");
            await MyMethod();
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "TestAsync方法结束");
        }

        //模拟耗时操作
        //重要说明:如果异步方法未使用await运算符标记暂停点,那么异步方法会作为同步方法执行,
        //即使有async修饰符,也不例外。
        static async Task MyMethod()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "异步执行" + i.ToString() + "..");
                await Task.Delay(1000); //模拟耗时操作
                //Thread.Sleep(1000); //不能用
            }
        }
    }
}

运行结果:


重要说明:如果异步方法未使用await运算符标记暂停点,那么异步方法会作为同步方法执行,即使有async修饰符,也不例外,结果如下:


示例二(有返回值):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "--主方法开始执行");
            Task<string> result = TestAsync();

            //如果此时用result.Result 获取异步结果,那么主线程将阻塞,等待异步线程返回结果后才继续执行
            //Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "--子任务返回结果:" + result.Result);
            
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "--主方法执行完毕!");
            Console.ReadKey();
        }

        static async Task<string> TestAsync()
        {
            string strRet = string.Empty;
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "TestAsync方法开始");
            //strRet = await Task.Run(() => Test()); //写法一
            strRet = await Test(); //写法二
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "TestAsync方法结束,结果:" + strRet);

            return strRet;
        }

        //模拟耗时操作
        //重要说明:如果异步方法未使用await运算符标记暂停点,那么异步方法会作为同步方法执行,
        //即使有async修饰符,也不例外。
        static async Task<string> Test()
        {
            await Task.Delay(5000);
            //Thread.Sleep(1000); //不能用
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "耗时任务执行。。。");
            return "ok";
        }
    }
}

运行结果:

说明:
异步方法的返回值要在异步方法里获取,否则异步失效,如:


推荐阅读