一、需求
如果调用一个异步方法后,一直不给返回值结果怎么办呢?这就涉及到怎么取消任务了。
二、Task取消任务
static CancellationTokenSource source = new CancellationTokenSource();static void Main(string[] args){Task.Run(() =>{for (int i = 0; i < 10; i++){Thread.Sleep(500);Console.WriteLine("oh my god");source.Token.ThrowIfCancellationRequested();}}, source.Token);Thread.Sleep(2000);Console.WriteLine("取消任务");source.Cancel();Console.ReadKey();}
换一个写法
static void Main(string[] args){bool isOut = false;var task1 = Task.Run(() =>{for (int i = 0; i < 100; i++){if (isOut) return;Console.WriteLine("执行中" + i);Thread.Sleep(500);}});Thread.Sleep(2000);Console.WriteLine("取消任务");isOut = true;Console.ReadKey();}
我在 for 循环中加入一个判断,如果等于 true,直接跳出循环,这不也可以中断任务
三、Task取消任务的回调
取消任务也是可以加入回调的,如下:
static CancellationTokenSource source = new CancellationTokenSource();static void Main(string[] args){var task1 = Task.Run(() =>{for (int i = 0; i < 100; i++){source.Token.ThrowIfCancellationRequested();Console.WriteLine("执行中" + i);Thread.Sleep(500);}}, source.Token);//在指定的毫秒数后取消task执行source.CancelAfter(2 * 1000);//取消任务后的回调source.Token.Register(() =>{//不延迟会获取不到正确的状态Thread.Sleep(50);Console.WriteLine("task1状态:" + task1.Status);Console.WriteLine("IsFaulted状态:" + task1.IsFaulted);//由于未处理的异常,任务已完成。Console.WriteLine("IsCompleted状态:" + task1.IsCompleted);//获取一个值,该值指示任务是否已完成。});Console.ReadKey();}
四、Task超时处理的实现
先来一个超时取消后续代码执行的方法
private static CancellationTokenSource Cancellation = new CancellationTokenSource();static void Main(string[] args){//设置超时的时间Cancellation.CancelAfter(TimeSpan.FromSeconds(1));Task.Run(() =>{try{Console.WriteLine("方法执行开始");//异步 Task.Delay 可以这么写,await Task.Delay(3000, Cancellation.Token)//效果同 Cancellation.Token.ThrowIfCancellationRequested() //await Task.Delay(3000, Cancellation.Token);Thread.Sleep(2000);Cancellation.Token.ThrowIfCancellationRequested();Console.WriteLine("方法执行结束");}catch (OperationCanceledException){Console.WriteLine("取消操作");}});Console.ReadKey();}
可以看到,方法执行结束这段代码并没有打印,这就是我们想要的效果了,在上面我们设置的超时时间是1秒,在后面的执行中,使用了线程睡眠时间是2秒,超时后,就自动取消操作了
把超时时间改为3秒,看看效果
private static CancellationTokenSource Cancellation = new CancellationTokenSource();
static void Main(string[] args)
{//设置超时的时间Cancellation.CancelAfter(TimeSpan.FromSeconds(3));Task.Run(() =>{try{Console.WriteLine("方法执行开始");//异步 Task.Delay 可以这么写,await Task.Delay(3000, Cancellation.Token)//效果同 Cancellation.Token.ThrowIfCancellationRequested() //await Task.Delay(3000, Cancellation.Token);Thread.Sleep(2000);Cancellation.Token.ThrowIfCancellationRequested();Console.WriteLine("方法执行结束");}catch (OperationCanceledException){Console.WriteLine("取消操作");}});Console.ReadKey();}
这回就没有取消任务的执行了,那么超时取消代码执行的效果就实现了。