一.CancellationToken结构体使用详解
包含的属性:
None:空
Register(Action callback):注册/取消监听
ThrowIfCancellationRequested():如果任务被取消,就抛出异常
CancelAfter():设置等待多长时间以后超时,单位毫秒
Cancel():直接发出退出信息
通过 CancellationToken Token 传递信息
如果异步方法存在CancellationToken参数的话可以通过传递 CancellationToken来实现
举例:var resp=await client.GetAsync(url,cancellationToke)
这种方式也是通过抛出异常来退出异步执行的
//这个例子展示的是通过手动捕获退出信号,然后退出,如果不进行手动捕获取消信号程序是不会退出的
static async Task Main(string[] args)
{
CancellationTokenSource cts=new CancellationTokenSource();
cts.CancelAfter(3000);
CancellationToken cToken=cts.Token;
await DownloadAsync("https://www.baidu.com",200,cToken);
}
static async Task DownloadAsync(string url,int Times,CancellationToken cancellationToken)
{
using(HttpClient client=new HttpClient())
{
for(int k=0;k<Times;k++)
{
string html=await client.GetStringAsync(url);
Console.WriteLine($"{DateTime.Now}:{html}");
//手动捕获退出信号
if(cancellationToken.IsCancellationRequested)
{
Console.WriteLine("收到退出的信号,执行退出");
break;
}
//下面这种事抛出异常的方式退出异步执行
//cancellationToken.ThrowIfCancellationRequested();
}
}
}
二:web开发使用情形,当用户关闭浏览器或者访问别的网页的时候该网页的请求如果在服务器端没有完成的,则服务器会自动终止访问请求,可以节省服务器资源
//vs mvc自动生成的代码
public IActionResult Index()
{
return View();
}
//将上面的代码修改为以下的形式传递CancellationToken参数,该参数是由.net框架自动传递的,不需要手动传递.
//当网页关闭或者刷新的时候框架会自动传递取消信号被HttpClient捕获并退出,所以异步方法尽量都传递CancellationToken参数
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
await DownloadAsync("https://163.com",50,cancellationToken);
return View();
}
static async Task DownloadAsync(string url,int n,CancellationToken cancellationToken)
{
using(HttpClient client=new HttpClient())
{
for(int i=0;i<n;i++)
{
var resp=await client.GetAsync(url,cancellationToken);
string strHtml=await resp.Content.ReadAsStringAsync();
Debug.WriteLine(strHtml);
}
}
}
三. Task类中 WhenAll与WhenAny的使用
1.Task WhenAny(IEnumerable tasks):只要tasks中的任何一个Task完成,即可向下执行
2.Task WhenAll(IEnumerable tasks):等待tasks中的Task全部完成,才会向下执行
3.FromResult():创建将普通数值转换为Task对象
static async Task Main(string[] args)
{
string [] files=Directory.GetFiles(@"E:\temp\a");
Task<int>[] countTasks=new Task<int>[files.Length];
for(int i=0;i<files.Length;i++)
{
string filename=files[i];
Task<int> t=ReadCharsCount(filename);
counttTasks[i]=t;
}
int[] counts=await Task.WhenAll(countTasks);
int c=counts.Sum();
Console.WriteLine(c);
}
static async Task<int> ReadCharsCount(string fileName)
{
string s=await File.ReadAllTextAsync(fileName);
return s.Length;
}