C# Task 及 async Task

本文深入探讨异步编程在.NET环境中的运用,详细解析await和Task关键字如何影响线程切换。异步方法不自动开启新线程,但await后的任务可能在子线程运行。Task.Result会阻塞主线程,而Task.Run确保任务在子线程执行。理解这些原理能有效减轻主线程压力并优化应用性能。
  1. 总结:符合异步方法语法的情况下,
    await 访问异步方法后面的代码行,一定是子线程, 
    Task 接受 访问异步方法后面的代码行 ,不Result 不会阻止主线,后面一定时主线程,
    如果Result,需要阻止当前线程,
  2.  使用 async task 尝试 ,
    异步方法本身不会节省 请求时间,但可以减轻主线程压力;
    异步方法内默认不会开启新线程(语法可通过),除非手动开启;通常手写异步方法需要task.run 开启新新增,
    语法才能保证正确。需要特别注意的是,在task.run之前为主线程,之后,线程会变为子线程,包括 awiat第一次await 后 catch finally 中 如图:

    如果 异步方法中,没有await的调用,不会开启新的线程,符合语法的await 可以开启新线程,包括Task.Dealy(n)
    如果 不用await 调用异步方法,调用异步方法 的前后代码都是主线程。
    注意: 在 await 后(通常有task.run),后面开启新线程,所有
     await Task.Delay(5000);//阻塞子线程
     Thread.Sleep(5000);//阻塞子线程,
  3. Task 方法
     方法声明为Task 的 ,方法中不能有 不允许await,
      Task 方法中有 开启了子线程,  被新线程体内和被调处await 之后的都为子线程,说明了阻塞,但新起线程之后则为 主线程,未被阻塞
    如图:
    标题

    代码中如果去掉 await ,值打印1个子线程 ,也不阻塞主线程 如图
    标题

  4. Task 接受TaskAsync 异步方法,Result之前,不会阻止主线程,等所有子线程完成,主线程顺序完成后才执行Result后代码

  5. Task 接受TaskAsync 异步方法,不会阻止主线程,
### C#Task async 的使用方法及常见问题 C# 中的 `Task` `async/await` 是实现异步编程的核心机制。以下将详细介绍其用法以及常见的问题。 #### 1. 基本概念 - **Task**:表示一个异步操作,通常用于返回结果或执行某些操作。`Task` 可以通过 `Task.Run` 或其他方式启动。 - **async**:修饰符,用于标记方法为异步方法。该方法中可以包含一个或多个 `await` 表达式。 - **await**:用于等待一个异步操作完成,而不会阻塞当前线程[^2]。 #### 2. 使用方法 ##### (1) 创建启动 Task 可以通过多种方式创建启动 `Task`: ```csharp Task task = new Task(() => Console.WriteLine("Task is running")); task.Start(); // 手动启动任务 await task; // 等待任务完成 ``` 或者使用更简洁的方式: ```csharp await Task.Run(() => Console.WriteLine("Task is running")); ``` ##### (2) 异步方法的基本结构 一个典型的异步方法如下所示: ```csharp static async Task DoAsyncWork() { Console.WriteLine("Starting async work..."); string result = await FetchDataAsync(); // 等待异步操作完成 Console.WriteLine($"Async work completed: {result}"); } ``` ##### (3) 处理返回值 如果需要从异步方法中返回值,可以使用 `Task<T>`: ```csharp static async Task<string> FetchDataAsync() { using (HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync("https://www.baidu.com/"); string content = await response.Content.ReadAsStringAsync(); return content; } } ``` ##### (4) 并发执行多个 Task 可以同时启动多个 `Task` 并等待它们全部完成: ```csharp Task task1 = Task.Delay(1000); Task task2 = Task.Delay(2000); await Task.WhenAll(task1, task2); // 等待所有任务完成 ``` #### 3. 常见问题及解决方案 ##### (1) 主线程被阻塞 如果直接调用 `Task.Result` 或 `Task.Wait()`,可能会导致主线程被阻塞[^4]。建议使用 `await` 来避免这种情况。 ##### (2) 异步方法未开启新线程 默认情况下,`async/await` 不会自动开启新线程。只有在显式使用 `Task.Run` 时才会开启新线程[^4]: ```csharp await Task.Run(() => Console.WriteLine("Running on a new thread")); ``` ##### (3) 忘记使用 `await` 如果忘记在调用异步方法时使用 `await`,可能会导致代码继续执行而不等待异步操作完成[^3]。 ##### (4) 异常处理 异步方法中的异常需要通过 `try-catch` 捕获,否则可能导致未处理的异常: ```csharp try { await FetchDataAsync(); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } ``` #### 4. 示例代码 以下是一个完整的示例,展示如何使用 `Task` `async/await`: ```csharp using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { await DoAsyncWork(); Console.WriteLine("Main method completed."); } static async Task DoAsyncWork() { Console.WriteLine("Starting async work..."); string result = await FetchDataAsync(); Console.WriteLine($"Async work completed: {result}"); } static async Task<string> FetchDataAsync() { using (HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync("https://www.baidu.com/"); string content = await response.Content.ReadAsStringAsync(); return content; } } } ``` ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值