Simple WPF: C# Task异步任务的取消初探
1.Simple WPF: WPF 透明窗体和鼠标事件穿透2.Simple WPF: WPF 自定义按钮外形3.Simple WPF: WPF 实现按钮的长按,短按功能4.Simple WPF: WPF自定义一个可以定义步长的SpinBox5.Simple WPF: C# 使用基本的async/await实现异步
6.Simple WPF: C# Task异步任务的取消初探
7.Simple WPF: WPF实现一个MINIO等S3兼容对象存储上传文件的小工具8.Simple WPF: S3实现MINIO大文件上传并显示上传进度9.Simple WPF: WPF使用Windows API发送Toast通知最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。
创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧!
C#中提供了CancellationTokenSource
来实现Task
的取消,方法就是在Task
异步循环中检测任务是否被取消。最近正在学习C#的任务异步模型,因此撰文以记之。
无法被取消的任务
原本以为Task
是运行在被.NET管理的线程池上的,可以直接通过Task.Run
传入的CancellationToken
进行取消。结果剧本不是我想的那样,这样根本停不下来。因此还是需要在循环中去判断任务是否被取消。
static async Task TaskCannotCancellationAsync()
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
Task task = Task.Run(() =>
{
Console.WriteLine("Task Can not Cancellation Running...");
Thread.Sleep(1000);
Console.WriteLine("Task Can not Cancellation Running...");
Console.WriteLine("Task Finished");
}, cancellationTokenSource.Token);
cancellationTokenSource.Token.Register(() => Console.WriteLine("Cancel Task."));
cancellationTokenSource.CancelAfter(500);
await task;
}
解下来介绍正确的可以被取消的异步任务写法。
基于异常的任务取消
我们在Task
的任务循环中检测Token
是否被取消。而取消之后就抛出异常,通过异常处理来中断原有的任务。
static async Task TaskCancellationAsync()
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
Task task = Task.Run(async () =>
{
token.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
Console.WriteLine("Task Cancellation Running...");
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
await Task.Delay(1000);
}
await Task.Delay(1000);
Console.WriteLine("Task Finished");
}, cancellationTokenSource.Token);
cancellationTokenSource.Token.Register(() => Console.WriteLine("Cancel Task."));
cancellationTokenSource.CancelAfter(500);
try
{
await task;
}
catch (OperationCanceledException e)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
}
finally
{
cancellationTokenSource.Dispose();
}
}
取消线程循环
既然我们可以这样取消一个死循环,那么博主就想试试看CancellationTokenSource
是否可以用于取消一个普通的线程。
static void ThreadProc(object? token)
{
CancellationToken? cancellationToken = (CancellationToken?)token;
while (!(cancellationToken?.IsCancellationRequested ?? true))
{
Console.WriteLine("ThreadMethod Working...");
Thread.Sleep(100);
}
}
static void ThreadAsync()
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Thread thread = new Thread(new ParameterizedThreadStart(ThreadProc));
thread.Start(cancellationTokenSource.Token);
cancellationTokenSource.CancelAfter(500);
}
测试后发现这么写也可以实现线程工作循环的取消。
完整的实验输出效果
参考链接#
https://cloud.tencent.com/developer/article/1895682
https://www.cnblogs.com/shanfeng1000/p/13402152.html
https://learn.microsoft.com/zh-cn/dotnet/standard/threading/cancellation-in-managed-threads
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析