C#中异步编程Async和Await的用法

C#5.0(.NET Framework 4.5)提供Async和Await关键字来实现异步编程。

关于使用这两个关键字官方说明如下:

  • 方法签名包含一个 Async 或 async 修饰符

  • 按照约定,异步方法的名称以“Async”后缀结尾。

  • 返回类型为下列类型之一:

    • 如果你的方法有操作数为 TResult 类型的返回语句,则为 Task<TResult>。

    • 如果你的方法没有返回语句或具有没有操作数的返回语句,则为 Task。

    • 如果你编写的是异步事件处理程序,则为 Void(Visual Basic 中为 Sub)。

    • 有关详细信息,请参见本主题后面的“返回类型和参数”(点击此处看官网完整说明)。

    • 方法通常包含至少一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控件返回到方法的调用方。 本主题的下一节将解释悬挂点发生的情况。

这里附上官方MSDN的链接:

 

//实例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("--------------------------------------------------------------------");
            Console.WriteLine("主线程开始执行,时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            Console.WriteLine("--------------------------------------------------------------------");            /*
            * 主线程调用ShowInfoAsync异步方法
            * 使用async和await关键字
            */
            ShowInfoAsync();
            Console.WriteLine(string.Empty);            /*同步操作*/
            for (int i = 0; i < 3; i++)
            {
                Thread.Sleep(1000);
                Console.WriteLine(string.Format("主线程同步:第{0}次循环,时间:{1}", i + 1, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
            }

            Console.WriteLine("--------------------------------------------------------------------");
            Console.WriteLine("主线程执行结束,时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            Console.WriteLine("--------------------------------------------------------------------");
            Console.ReadKey();
        }
        /// <summary>
        /// 异步显示输出信息
        /// </summary>
        static async void ShowInfoAsync()
        {

            //声明要调用的异步方法,获取异步任务操作类 Task
            //Task<string> getTask = GetDataAsync();

            Console.WriteLine(string.Empty);
            Console.WriteLine(string.Format("开始执行异步获取数据方法,时间:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));            /*
             * 异步获取数据并显示
             * 这里使用 await 关键词启用并等待异步返回结果
             * 在声明await关键词的地方线程就会在此等待返回结果
             * 只有返回结果才会继续执行下面步骤
             */
            string strShowString = await GetDataAsync();

            Console.WriteLine("***************************************************************");
            Console.WriteLine(string.Format("异步获取数据执行结束,获取数据值:{0},时间:{1}", strShowString, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
            Console.WriteLine("***************************************************************");
            Console.WriteLine(string.Empty);
        }
        /// <summary>
        /// 异步获取返回的数据
        /// </summary>
        /// <returns></returns>
        static async Task<string> GetDataAsync()
        {            //这里也可以使用Task.Run
            return await Task.Run(() =>
            {
                string strReturn = string.Empty;
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine(string.Format("异步:第{0}次循环,时间:{1}", i + 1, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                    strReturn += i.ToString();
                }
                return strReturn;
            });
        }
    }
}

//例子中如果是同步编程的话一共循环8次需要3+5=8秒,而使用异步编程的话只需要5秒,节省了3秒

项目应用

private async void button1_Click(object sender, EventArgs e)
{
    var t = Task.Run(() => {
        Thread.Sleep(5000);
        return "webapi";
    });
    textBox1.Text = await t;
}

 Task.Run用法

Task 启动的线程默认为线程池里的,启动后默认为后台线程

1、无参无返回值

Task.Run(Test);

public void Test()
{
    //...to...
    
}

2、无参有返回值

//以string返回值为例,Task<string>中的<string>可省略
//task前面的var也可以直接写Task<string>,这里如果直接写的话不能将<string>省略
var task=Task.Run(Test);
string result=task.Result;
    
public string Test()
{
    //...todo...
    
    return "str";
}

3、有参无返回值

//以string参数为例
string str="str...";
Task.Run(()=>Test(str));

public void Test(string str)
{
    //...todo...
    
}

4、有参有返回值

//这里以参数为int,返回值string为例
int num = 10 ;
var task = Task.Run(() => Test(num));
string result = task.Result;

public string Test(int n)
{
    //...todo...
    
    return "str...";
}

//例如添加日志

/// <summary>
        /// 添加操作日志
        /// </summary>
        /// <param name="caozuo"></param>
        public void AddLog(string caozuo)
        {
            ActionLog model = new ActionLog()
            {
                userID = LoginUser.id,
                username = LoginUser.username,
                name = LoginUser.name,
                times = System.DateTime.Now,
                caozuo = caozuo
            };
            Task.Run(() =>
            {
                new ActionLogBLL().Add(model);
            });
        }

 

posted @ 2021-08-31 14:19  WebApi  阅读(1231)  评论(0编辑  收藏  举报
CopyRight © 博客园 WebAPI