C#异步使用需要注意的问题 C#异步使用需要注意的几个问题
天之客 人气:0想了解C#异步使用需要注意的几个问题的相关内容吗,天之客在本文为您仔细讲解C#异步使用需要注意的问题的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:C#异步使用,C#异步,下面大家一起来学习吧。
一、异步模型的基本概述
异步编程的核心是 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(); } } }
加载全部内容