问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C#异步编程:高效开发者的秘密武器

创作时间:
作者:
@小白创作中心

C#异步编程:高效开发者的秘密武器

引用
CSDN
9
来源
1.
https://blog.csdn.net/m0_67412019/article/details/141200776
2.
https://blog.csdn.net/m0_38141444/article/details/144793710
3.
https://blog.csdn.net/Raink_LH/article/details/128352458
4.
https://zhuanlan.zhihu.com/p/465119797
5.
https://cloud.tencent.com/developer/article/2381657
6.
https://learn.microsoft.com/zh-cn/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
7.
https://wangshenjie.com/index.php/archives/118/
8.
http://www.imooc.com/article/367867
9.
https://www.cnblogs.com/taylorshi/p/14827711.html

在现代软件开发中,C#的异步编程成为提升应用程序响应性和性能的关键技术之一。通过使用asyncawait关键字,开发者能够轻松处理耗时操作(如I/O操作、网络请求等),避免阻塞主线程,从而提高用户体验和系统性能。

01

什么是异步编程?

在同步编程中,执行的每个任务都会阻塞当前线程,直到任务完成。而在异步编程中,任务在等待时不会阻塞线程,其他任务可以继续执行,直到被等待的任务完成。这种非阻塞的执行方式,使得应用程序能够在处理I/O密集型操作时保持响应性,从而提高用户体验和系统性能。

异步编程的优势

  • 提高响应性:异步操作使得长时间运行的任务不会阻塞主线程,增强用户体验,特别是在UI应用中。
  • 更高效的资源利用:异步操作不会占用线程,尤其适用于I/O操作(如文件读写、网络请求等),让CPU更高效地处理其他任务。
  • 简化代码结构asyncawait可以避免回调地狱,使得异步编程像同步代码一样简洁、易于理解。
02

`async`和`await`的基本使用

async关键字

async关键字用于标记一个方法为异步方法。异步方法必须返回一个TaskTask<T>,表示该方法的异步执行结果。

示例:使用async定义异步方法

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("异步任务开始");

        // 调用异步方法
        await ExampleAsyncMethod();
        
        Console.WriteLine("异步任务完成");
    }

    // 使用 async 关键字标记方法为异步方法
    static async Task ExampleAsyncMethod()
    {
        Console.WriteLine("开始执行异步任务...");
        
        // 模拟一个异步操作,例如 I/O 操作
        await Task.Delay(2000); // Task.Delay 模拟了一个耗时 2 秒的异步操作
        
        Console.WriteLine("异步任务完成");
    }
}

在此代码中,ExampleAsyncMethod被标记为async,并且返回一个Taskawait Task.Delay(2000)模拟了一个耗时2秒的异步操作。当await等待任务完成时,主线程会继续执行其他任务,而不会被阻塞。

await关键字

await关键字用于等待一个异步操作的完成。当执行到await时,控制权会返回到调用await的位置,直到任务完成。

示例:使用await等待异步任务

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("开始执行异步操作");

        // 异步调用
        await PerformTaskAsync();
        
        Console.WriteLine("异步操作完成");
    }

    static async Task PerformTaskAsync()
    {
        // 模拟一个耗时的异步任务
        await Task.Delay(1000); // 延迟 1 秒
        
        Console.WriteLine("任务执行完毕");
    }
}

在此代码中,PerformTaskAsync是一个异步方法,它通过await Task.Delay(1000)模拟了一个耗时1秒的任务。在Main方法中,调用了await PerformTaskAsync(),并且等待异步操作完成后,继续执行后续代码。

异步方法的返回类型

异步方法通常返回以下几种类型:

  • Task:表示没有返回值的异步操作。
  • Task<T>:表示有返回值的异步操作,T是返回值的类型。
  • ValueTask:一种轻量级的任务类型,适用于快速完成的异步方法,可以避免不必要的内存分配。

示例:有返回值的异步方法

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // 异步调用返回值
        int result = await PerformCalculationAsync(5, 3);
        Console.WriteLine($"计算结果: {result}");
    }

    static async Task<int> PerformCalculationAsync(int a, int b)
    {
        await Task.Delay(1000); // 模拟延迟
        return a + b;
    }
}

在这个示例中,PerformCalculationAsync方法返回一个Task<int>,表示异步操作的返回值。await等待该任务完成后,获取计算结果。

03

实际应用场景

独立任务并行执行

public static async Task Method1()
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Method 1");
        }
    });
}

public static void Method2()
{
    for (int i = 0; i < 25; i++)
    {
        Console.WriteLine("Method 2");
    }
}

在这个例子中,Method1Method2并行运行,互不影响。

处理依赖关系

public static async Task<int> Method1()
{
    int count = 0;
    await Task.Run(() =>
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Method 1");
            count++;
        }
    });
    return count;
}

public static void Method3(int count)
{
    Console.WriteLine($"Total count is {count}");
}

public static async void CallMethods()
{
    Task<int> task = Method1();
    Method2();
    int result = await task;
    Method3(result);
}

这里,Method3依赖于Method1的结果。通过await,程序确保Method1完成后才调用Method3

文件读取

static async Task<int> ReadFile(string filePath)
{
    using (StreamReader reader = new StreamReader(filePath))
    {
        string content = await reader.ReadToEndAsync();
        return content.Length;
    }
}

此示例展示了如何异步读取文件内容,并返回其长度。

04

最佳实践

  1. 命名规范:异步方法应以"Async"结尾
  2. 避免异步void方法:改用Task或Task以支持异常处理和等待
  3. 使用ConfigureAwait(false):在不需要恢复到原始上下文时优化性能
  4. 异常处理:使用try/catch包围await调用
  5. 避免深度嵌套的异步代码:减少代码复杂性
  6. 使用CancellationToken:提供取消功能,增强响应性
  7. CPU密集型任务使用Task.Run:I/O操作则直接使用异步API

通过合理使用asyncawait,可以显著提升应用程序的性能和用户体验。掌握异步编程是每个C#开发者必备的技能,它能帮助你编写出更高效、更响应的软件系统。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号