System.Threading.Tasks.Task
和
System.Threading.Tasks.Task<TResult>
类支持使用取消令牌进行取消。 有关详细信息,请参阅
托管线程中的取消
。 在 Task 类中,取消涉及用户委托间的协作,这表示可取消的操作和请求取消的代码。 成功取消涉及调用
CancellationTokenSource.Cancel
方法的请求代码,以及及时终止操作的用户委托。 可以使用以下选项之一终止操作:
从委托中返回。 在许多情况下,此选项就足够了。 但是,采用这种方式取消的任务实例会转换为
TaskStatus.RanToCompletion
状态,而不是
TaskStatus.Canceled
状态。
引发
OperationCanceledException
,并将其传递到在其上请求了取消的标记。 完成此操作的首选方式是使用
ThrowIfCancellationRequested
方法。 采用这种方式取消的任务会转换为 Canceled 状态,调用代码可使用该状态来验证任务是否响应了其取消请求。
下面的示例演示引发异常的任务取消的基本模式:
标记将传递到用户委托和任务实例。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
static async Task Main()
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Run(() =>
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}, tokenSource2.Token); // Pass same token to Task.Run.
tokenSource2.Cancel();
// Just continue on this thread, or await with try-catch:
await task;
catch (OperationCanceledException e)
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
finally
tokenSource2.Dispose();
Console.ReadKey();
Imports System.Threading
Imports System.Threading.Tasks
Module Test
Sub Main()
Dim tokenSource2 As New CancellationTokenSource()
Dim ct As CancellationToken = tokenSource2.Token
Dim t2 = Task.Factory.StartNew(Sub()
' Were we already canceled?
ct.ThrowIfCancellationRequested()
Dim moreToDo As Boolean = True
While moreToDo = True
' Poll on this property if you have to do
' other cleanup before throwing.
If ct.IsCancellationRequested Then
' Clean up here, then...
ct.ThrowIfCancellationRequested()
End If
End While
End Sub _
, tokenSource2.Token) ' Pass same token to StartNew.
' Cancel the task.
tokenSource2.Cancel()
' Just continue on this thread, or Wait/WaitAll with try-catch:
t2.Wait()
Catch e As AggregateException
For Each item In e.InnerExceptions
Console.WriteLine(e.Message & " " & item.Message)
Finally
tokenSource2.Dispose()
End Try
Console.ReadKey()
End Sub
End Module
有关完整示例,请参阅如何:取消任务及其子级。
当任务实例观察到用户代码引发的 OperationCanceledException 时,它会将该异常的标记与其关联的标记(传递到创建任务的 API 的标记)进行比较。 如果标记相同,并且标记的 IsCancellationRequested 属性返回 true
,则任务会将此解释为确认取消并转换为“已取消”状态。 如果不使用 Wait 或 WaitAll 方法来等待任务,则任务只会将其状态设置为 Canceled。
如果在等待的任务转换为“已取消”状态,就会引发 System.Threading.Tasks.TaskCanceledException 异常(包装在 AggregateException 异常中)。 此异常表示成功取消,而不是有错误的情况。 因此,任务的 Exception 属性返回 null
。
如果标记的 IsCancellationRequested 属性返回 false
,或者异常的标记与任务的标记不匹配,则会将 OperationCanceledException 按照普通的异常来处理,从而导致任务转换为“已出错”状态。 其他异常的存在将也会导致任务转换为“已出错”状态。 您可以在 Status 属性中获取已完成任务的状态。
在请求取消操作之后,任务可能还会继续处理一些项。
托管线程中的取消
如何:取消任务及其子级