C#中如何使用异步编程

C#异步编程的使用与优势

在 C# 中,异步编程主要通过 async 和 await 关键字来实现。异步编程的目的是让程序在执行耗时操作(如 I/O 操作、网络请求等)时不会阻塞主线程,从而提高程序的性能。

1. 异步编程的核心概念

async 关键字

  • 用于标记一个方法为异步方法。

  • 异步方法的返回类型通常是 TaskTask<T> 或 ValueTask

  • Task:表示一个没有返回值的异步操作。

  • Task<T>:表示一个返回类型为 T 的异步操作。

  • ValueTask:轻量版的 Task,适用于高性能场景。

await 关键字

  • 用于暂停异步方法的执行,直到等待的任务完成。

  • await 只能用于 async 方法中。

  • 它不会阻塞线程,而是将控制权交回给调用方,直到任务完成后再恢复执行。

2. 异步编程的基本语法

定义异步方法

public async Task GetDataAsync()
{
    // 异步操作
    await Task.Delay(1000); // 模拟耗时操作
}

调用异步方法

public async Task CallAsyncMethod()
{
    await GetDataAsync(); // 等待异步方法完成
    Console.WriteLine("异步方法已调用.");
}

3. 异步编程的使用场景

I/O 密集型操作
  • 文件读写、数据库查询、网络请求等操作通常需要较长时间,使用异步编程可以避免阻塞主线程。

UI 应用程序
  • 在桌面或移动应用程序中,保持 UI 线程的响应性极为重要。异步操作可以防止 UI 卡顿,提升用户体验。

Web 应用程序
  • 在 ASP.NET 等 Web 应用程序中,异步操作可以提高服务器的吞吐量,处理更多的并发请求。

并行任务
  • 当需要同时执行多个独立的任务时,可以使用异步编程来提高效率。

4. 异步编程的示例

1:简单的异步方法

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("开始异步操作...");
        await DoSomethingAsync();
        Console.WriteLine("异步操作已完成.");
    }

    static async Task DoSomethingAsync()
    {
        await Task.Delay(2000); // 模拟耗时操作(2秒)
        Console.WriteLine("DoSomethingAsync方法异步任务已完成.");
    }
}

输出:

开始异步操作...
DoSomethingAsync方法异步任务已完成.
异步操作已完成.

2:异步文件读写

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string filePath = "task-test.txt";
        string content = "hello async";

        // 异步写入文件
        await WriteFileAsync(filePath, content);
        Console.WriteLine("文件已写入");

        // 异步读取文件
        string readContent = await ReadFileAsync(filePath);
        Console.WriteLine("文件内容: " + readContent);
    }

    static async Task WriteFileAsync(string filePath, string content)
    {
        await File.WriteAllTextAsync(filePath, content);
    }

    static async Task<string> ReadFileAsync(string filePath)
    {
        return await File.ReadAllTextAsync(filePath);
    }
}

输出:

文件已写入
文件内容: hello async

3:异步网络请求

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string url = "https://xxxxx.com";
        string content = await DownloadContentAsync(url);
        Console.WriteLine("Content: " + content);
    }

    static async Task<string> DownloadContentAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            return await client.GetStringAsync(url);
        }
    }
}

4:并行异步任务

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Task<string> task1 = DownloadContentAsync("https://xxx.com");
        Task<string> task2 = DownloadContentAsync("https://xxx2.com");

        string[] results = await Task.WhenAll(task1, task2);
        Console.WriteLine("Task 1 result: " + results[0]);
        Console.WriteLine("Task 2 result: " + results[1]);
    }

    static async Task<string> DownloadContentAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            return await client.GetStringAsync(url);
        }
    }
}

5. 异步编程的注意事项

1、避免 async void

• 除了事件处理程序外,尽量避免使用 async void 方法,因为它无法被等待,且异常无法被捕获。

2、正确处理异常:

• 使用 try-catch 块来捕获异步方法中的异常。

try
{
    await GetDataAsync();
}
catch (Exception ex)
{
    Console.WriteLine("Error: " + ex.Message);
}

3、避免阻塞异步代码:

• 不要使用 .Result 或 .Wait() 来阻塞异步任务,这可能导致死锁。

• 始终使用 await 来等待异步任务。

  • 4、性能优化:

    • 对于高性能场景,可以使用 ValueTask 代替 Task

6. 异步编程的好处

1、提高响应性:

• 异步操作不会阻塞主线程,使得应用程序在等待耗时操作时保持响应。

2、提高资源利用率:

• 异步操作可以更高效地利用系统资源,特别是在 I/O 密集型操作中。

3、简化代码:

• 使用 async 和 await 可以使异步代码的结构更加清晰,易于理解和维护。

总结

C# 中的异步编程通过 async 和 await 关键字实现,能够显著提高程序的响应性和性能。它特别适用于 I/O 密集型操作、UI 应用程序和 Web 应用程序等场景。通过合理使用异步编程,可以编写出高效、简洁且易于维护的代码。

文章转载自:代码拾光

原文链接:C#中如何使用异步编程 - 代码拾光 - 博客园

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

### 异步编程模型的核心概念 C# 中的异步编程模型主要依赖于 `Task` 和 `Task<T>` 对象,这两个对象对异步操作建模,并受到 `async` 和 `await` 关键字的支持。异步编程的核心在于提高应用程序的响应性和性能,尤其是在处理 I/O 绑定和 CPU 绑定任务时。通过合理运用这些技术,可以显著提升用户体验[^4]。 #### 异步编程的优势 异步编程能够显著提高应用程序的响应性,特别是在用户界面应用中。当执行耗时操作时,如网络请求或文件读写,异步编程允许应用程序保持响应状态,而不是冻结或无响应。此外,异步编程还有助于提高资源利用率,减少线程阻塞,从而提高整体性能[^1]。 #### 异步编程的实现 在 C# 中,使用 `async` 和 `await` 关键字可以轻松实现异步编程。`async` 关键字用于标记一个方法为异步方法,而 `await` 关键字则用于等待异步操作的完成,而不会阻塞当前线程。对于 I/O 绑定代码,当 `await` 一个操作时,它将返回 `async` 方法中的一个 `Task` 或 `Task<T>`。对于 CPU 绑定代码,当 `await` 一个操作时,它将在后台线程通过 `Task.Run()` 方法启动。 #### 异步编程使用建议 在使用异步编程时,需要注意一些关键点。首先,确保正确识别 CPU 绑定和 I/O 绑定工作,以便选择合适的异步编程方法。其次,处理异常和资源管理是至关重要的,以确保程序的稳定性和可靠性。最后,避免在 `async` 方法的主体中不使用 `await`,因为这会导致 C# 编译器生成的状态机无法完成任何任务,从而影响效率[^3]。 #### 示例代码 下面是一个简单的异步编程示例,展示了如何使用 `async` 和 `await` 关键字: ```csharp public async Task<int> FetchDataAsync() { // 模拟一个异步操作,例如网络请求 var result = await Task.Run(() => { // 模拟耗时操作 Thread.Sleep(2000); return 42; }); return result; } public async void StartFetching() { Console.WriteLine("开始获取数据..."); var data = await FetchDataAsync(); Console.WriteLine($"数据获取完成: {data}"); } ``` 在这个示例中,`FetchDataAsync` 方法是一个异步方法,它使用 `await` 关键字等待一个 `Task` 完成。`StartFetching` 方法调用了 `FetchDataAsync` 并等待其结果,同时不会阻塞主线程。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值