C#异步使用需要注意的几个问题
作者:天之客 发布时间:2023-03-05 04:33:08
一、异步模型的基本概述
异步编程的核心是 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();
}
}
}
来源:https://www.tuicool.com/articles/2muY73I


猜你喜欢
- mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多。由于很多公司使用了云服务,服务器默
- 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子
- 需求:按照起始日期查询出数据库里一段连续日期的住院信息。问题:数据库里的住院信息可能不是完整的,也就是在给出的日期区间里只有若干天的数据,缺
- 前言在一些项目中,经常会遇到需要把当前线程中的上下文传递到其他线程中的情况,比如某项目包含国际化操作,在业务请求进来时需要把对应的国家代码存
- C#史上最简单读写xml文件方式,创建控制台应用程序赋值代码,就可以运行,需要改动,请自行调整using System;using Syst
- 文件的读取 FileStream fs = new FileStream(@"D:\12.txt", File
- 前言无意中翻到几年前写过的一个RatingBar,可以拖拽,支持自定义星星图片,间距大小等参数。自定义参数为了方便扩展,支持更多的样式,这里
- 在开始之前,我先卖个关子提一个问题:假设我们有一个Movie类,这个类有三个成员变量分别是starred(是否收藏), title(电影名称
- 对一个集合中的对象进行排序,根据对象的某个指标的大小进行升序或降序排序。代码如下:进行降序排列 进行降序排列 Co
- 1、配置 IDEA 的 Maven 环境单击菜单栏中的 File → Settings → Build, Ex
- 前言这段时间在学习Spring,依赖注入DI和面向切面编程AOP是Spring框架最核心的部分。这次主要是总结依赖注入的bean的装配方式。
- 在一些项目的实际开发过程中,我们有时候需要对GridControl中列值进行转义,譬如1转义成“完成”等等,一般在诸如CustomColum
- Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(
- C# 5.0 给我们带来了三个非常有用的编译器特性CallerMemberNameCallerFilePathCallerLineNumbe
- package org.itat.stax;import java.io.IOException;import java.io.InputS
- 需求有一个固定URL的文件,服务器端程序会定期的更新这个文件,现在需要写一个工具来监控这个文件的变化。解决办法最初我想到的是把这个文件下载下
- 面试题1:说一下抽象类和接口有哪些区别?正经回答:抽象类和接口的主要区别:从设计层面来说,抽象类是对类的抽象,是一种模板设计;接口是行为的抽
- DozerDozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵
- 文件上传的方法主要目前有两个常用的,一个是SmartUpload,一个是Apache的Commons fileupload.我们这里主要介绍
- 1、TCP/IP层次模型当然这里我们只讨论重要的四层01,应用层(Application):应用层是个很广泛的概念,有一些基本相同的系统级T