C#中如何取消MDI子窗体中的异步任务?
如何在窗体卸载或点击取消按钮时取消后台任务
要实现任务取消,核心是用CancellationTokenSource和CancellationToken,这是.NET中任务取消的标准协作式方案,步骤如下:
1. 声明取消令牌源字段
在你的MDI子窗体类中添加一个CancellationTokenSource字段,用来跨方法管理取消信号:
private CancellationTokenSource _cts;
2. 修改任务方法,支持取消
更新BuscaActualizaciones和DoLongThing方法,传入取消令牌,并在耗时操作中定期检查取消请求:
private async void BuscaActualizaciones() { try { // 将取消令牌传递给Task.Run和耗时方法 await Task.Run(() => DoLongThing(_cts.Token), _cts.Token); } catch (OperationCanceledException) { // 任务被取消时的自定义处理,比如提示用户 MessageBox.Show("任务已取消"); } } private void DoLongThing(CancellationToken token) { // 你的耗时操作逻辑,需要在关键节点检查取消信号 // 示例:模拟循环执行的耗时任务 for (int i = 0; i < 100; i++) { // 检查是否收到取消请求,若有则抛出异常终止任务 token.ThrowIfCancellationRequested(); // 这里替换成你的实际耗时代码 System.Threading.Thread.Sleep(100); } }
3. 启动任务时初始化取消令牌源
修改搜索按钮的点击事件,每次启动新任务前先清理旧的令牌源,避免冲突:
private void BtnBuscar_Click(object sender, EventArgs e) { // 若之前有任务在运行,先取消并释放资源 _cts?.Cancel(); _cts?.Dispose(); // 创建新的取消令牌源 _cts = new CancellationTokenSource(); // 启动任务 BuscaActualizaciones(); }
4. 实现取消按钮逻辑
添加取消按钮的点击事件,触发任务取消:
private void BtnCancelar_Click(object sender, EventArgs e) { // 发送取消信号 _cts?.Cancel(); }
5. 窗体卸载时清理任务
在窗体的FormClosing事件中处理取消,确保窗体关闭时任务停止并释放资源:
private void Form_FormClosing(object sender, FormClosingEventArgs e) { _cts?.Cancel(); _cts?.Dispose(); }
关键说明
- 任务取消是协作式的:必须在
DoLongThing的耗时操作中定期调用token.ThrowIfCancellationRequested(),否则任务不会主动停止。如果你的耗时操作是单次调用的外部方法,需要看该方法是否支持传入CancellationToken。 - 每次启动新任务前必须清理旧的
CancellationTokenSource,否则会导致旧任务的取消信号干扰新任务。 OperationCanceledException是任务取消时的正常异常,捕获后可以做友好提示或清理工作。
内容的提问来源于stack exchange,提问作者Dav3
相关产品推荐
相关产品推荐

