C# async / await 用法以及和Task的关系

在C#5.0中,出现的async和await关键字是用于简化异步编程的强大工具。它们使得编写异步代码更加直观和易于理解。要完全理解async和await,首先需要理解它们与Task的关系。

Task 基础

在C#中,Task是表示一个异步操作的类。它可以封装一个异步操作,比如文件I/O、网络请求等。Task对象可以处于三种状态之一:未开始(Not Started)、正在运行(Running)或已完成(RanToCompletion)。

需要详细了解的可以看 上一篇文章 https://blog.csdn.net/pu_yu_hun_jin/article/details/154906054

async 关键字

async关键字用于声明一个方法为异步方法。当一个方法被声明为async时,它会自动返回一个Task或Task对象,其中T是方法的返回类型。这使得你可以在不阻塞调用线程的情况下执行耗时的操作。

例如:

csharp 复制代码
public async Task<int> GetDataAsync()
{
    // 模拟异步操作,比如网络请求
    await Task.Delay(10000); // 异步等待1秒
    return 42; // 返回结果
}

await 关键字

await关键字用于等待一个异步操作的完成。当在异步方法中使用await时,它会暂停当前方法的执行,直到被等待的异步操作完成。当异步操作完成后,控制流会恢复并继续执行后续代码。这允许主线程不被阻塞,从而提升应用程序的响应性和性能。

例如:

csharp 复制代码
public async Task CallAsyncMethod()
{
    int result = await GetDataAsync(); // 等待GetDataAsync完成
    Console.WriteLine(result); // 继续执行
}

async 和 await 的关系和作用

‌1、声明异步方法‌:使用async关键字声明一个方法为异步方法。这允许该方法的返回类型为Task或Task。

2、‌等待异步操作‌:在异步方法内部,使用await关键字等待另一个异步操作完成。这不会阻塞调用线程,允许其他操作继续执行。

3‌、简化异步编程‌:结合使用async和await,可以使得编写和处理异步代码变得更加简单和直观。

示例:完整流程,比如在Winform中

csharp 复制代码
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        Task task = GetDataAsync();
        Console.WriteLine(11111); // 返回结果

    }
    public async Task GetDataAsync()
    {
        // 模拟异步操作,比如网络请求
        await Task.Delay(10000); // 异步等待10秒
        Console.WriteLine(42234); // 返回结果
    }
}

这里会先打印出11111,然后等待10秒 会在打印出 42234,并且 此期间,可以进行其它操作,比如 移动 窗口,或者 点击其它按钮等,都是不阻塞的。

例子:

csharp 复制代码
namespace 异步编程
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Task task = FunAsync();
            Console.WriteLine("主线程"); // 返回结果

        }
        public async Task FunAsync()
        {
            Console.WriteLine("Before calling GetDataAsync");
            await GetDataAsync(); // 等待异步操作完成,才往下一行执行
            Console.WriteLine("After calling GetDataAsync");
        }

        /// <summary>
        /// 一个耗时操作
        /// </summary>
        /// <returns></returns>
        private Task GetDataAsync()
        {
            Task task1 = new Task(() =>
            {
                Console.WriteLine("开始执行耗时操作");
                Thread.Sleep(10000);
                Console.WriteLine("结束执行耗时操作"); // 返回结果
            });
            task1.Start();
            return task1;
        }
    }
}

运行过程

在这个例子中,当调用GetDataAsync()时,控制流会暂停在await表达式处,直到GetDataAsync()完成;而且Winform页面可以正常移动。一旦完成,控制流会继续执行到await下一行代码。这确保了即使在等待异步操作完成时,主线程也不会被阻塞

总结为:async / await 本身不是异步,而是用来简化异步操作的,异步还是线程干的活,常和Task配合。只要记得 哪个方法里使用await ,哪个方法会暂停往下执行,直至 await 后面跟的异步方法执行完成,才会继续往下进行;在这等待期间不影响其它操作。

相关推荐
泛凡(Linyongui)13 小时前
基于 CW32L010 的智能厨卫调温旋钮方案--低成本 EC21 编码旋钮全解析
单片机·嵌入式硬件·c#
暴走约伯15 小时前
【VFX工具链源码拆解 02】告别机械劳动(上):一键统改百个子粒子颜色与批量重命名
3d·unity·c#·材质
信息安全失业大专人员16 小时前
每日了解一个智能体-WorkBuddy
开发语言·ai·c#·智能体
呆呆敲代码的小Y17 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
淡海水18 小时前
09-01-内存-Unity资源生命周期全景
unity·c#·游戏引擎·.netcore·gc
椒颜皮皮虾྅21 小时前
让 C# 读懂整张图:DeploySharp 驱动 PaddleOCR v4/v5/v6,打通 OCR 全流程
开发语言·人工智能·深度学习·学习·c#·ocr·cuda
昂好的day21 小时前
C# 同步异步与多线程:Thread / Task / 线程池一次讲透(上篇)
开发语言·windows·c#
吃一碗粉只付一碗钱1 天前
12-给SPA友好的401和403响应
c#·状态模式
DLite1 天前
并发语言实现(二):锁与原子操作
多线程·并发·锁·原子操作
caimouse2 天前
MonoDevelop 编译用户应用程序时调用的是哪个编译器
c#