C#异步使用需要注意的几个问题
作者:天之客
C#使用异步方法中,使用一下关键词的时候徐注意一些问题,比如async 方法需在其主体中具有 await 关键字,否则它们将永不暂停,接下来文字里将为大家举例说明
一、异步模型的基本概述
异步编程的核心是 Task
和 Task<T>
对象,这两个对象对异步操作建模。 它们受关键字 async
和 await
的支持。 在大多数情况下模型十分简单:
对于 I/O 绑定代码,当你 await
一个操作,它将返回 async
方法中的一个 Task
或 Task<T>
。
对于 CPU 绑定代码,当你 await
一个操作,它将在后台线程通过 Task.Run()
方法启动。
二、C#异步使用需要注意的几个问题
- 异步方法如果只是对别的方法的简单的转发调用,没哟复杂的逻辑(比如等待A的结果,再调用B,等待A调用的返回值拿到内部做一些处理再返回),那么就可以去掉async关键字。
- 异步方法其实使用async 关键字clr多了一些准备和 转换的处理和线程的切换,效率反而低。
- 异步方法中想暂停一段时间,不要用thread.sleep(),因为他会阻塞调用线程导致当前界面卡无响应,而要用await task.delay(); 例如6秒后下载一个文件
- 异步中的CancellationToken 参数,用于提前终止任务,比如取消任务,请求超时
三、CancellationToken 结构体
- None 空
- bool IsCancellationToken 是否取消
- Register(action callback)注册取消监听
- ThrowIfCancellationRequested 如果任务被取消,执行到这句话就抛异常
- CancellationTokenSource 来创建 CancellationToken
- CancelAfter()超时后发出取消信号
- Cancel()发出取消信号
- CancellationToken Token
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(5000); //超时5s后取消 await DownloadString("http://www.baidu.com", 50, cts.Token); }
1.手动取消
if (cancellationToken.IsCancellationRequested) { Console.WriteLine("任务被取消"); break; }
2.利用方法取消,抛出异常
cancellationToken.ThrowIfCancellationRequested();
3. 传参数取消
系统自带的异步方法,只需要传参数就可取消,抛出异常
var resp= await client.GetAsync(url,cancellationToken);
4.手动触发事件取消任务
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); //cts.CancelAfter(5000); DownloadString("http://www.baidu.com", 100, cts.Token); //和超时区别在于去掉了前面的await 才生效 while (Console.ReadLine() != "q") { } cts.Cancel(); Console.ReadLine(); }
.Asp.net core Mvc
控制器里面的异步方法尽量带 CancellationToken
5.Task类方法
WhenAny
任何一个Task
完成,task
就完成WhenAll
所有任务都完成,才完成 。 不在乎Task
执行顺序FromResult
创建普通数值的Task
对象
6.yield流水线返回
yield 可以流水线返回,提高性能。
C# 8.0以上支持 yield异步方法的使用
static async IAsyncenumerable<string> test() { yield return "a"; yield return "b"; yield return "c"; }
调用:
await foreach(var o in test()) { Console.WriteLine(o); }
public static async Task DownloadString(string url,int num,CancellationToken cancellationToken) { try { using (var client = new HttpClient()) { for (int i = 0; i < num; i++) { string html = await client.GetStringAsync(url); Console.WriteLine($"{DateTime.Now}:{html}"); //1.手动取消 if (cancellationToken.IsCancellationRequested) { Console.WriteLine("任务被取消"); break; } //2.抛出异常 //cancellationToken.ThrowIfCancellationRequested(); } } } catch (Exception) { throw; } } public static async Task Download2String(string url, int num, CancellationToken cancellationToken) { using (var client = new HttpClient()) { for (int i = 0; i < num; i++) { var resp= await client.GetAsync(url,cancellationToken); string html =await resp.Content.ReadAsStringAsync(); Console.WriteLine($"{DateTime.Now}:{html}"); //1.手动取消 //if (cancellationToken.IsCancellationRequested) //{ // Console.WriteLine("任务被取消"); // break; //} //2.抛出异常 //cancellationToken.ThrowIfCancellationRequested(); } } }
到此这篇关于C#使用异步需要注意的几个问题的文章就介绍到这了,更多相关C#使用异步需要注意的问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!