Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Классы System.Threading.Tasks.Task и System.Threading.Tasks.Task<TResult> поддерживают отмену с помощью маркеров отмены. Дополнительные сведения см. в разделе Отмена в управляемых потоках. В классах Task отмена включает сотрудничество между делегатом пользователя, который представляет отменяемую операцию, и кодом, запрашивающим отмену. Успешная отмена подразумевает, что запрашивающий код вызывает метод CancellationTokenSource.Cancel, а делегат пользователя своевременно завершает операцию. Вы можете завершить операцию с помощью одного из следующих вариантов:
Возвращаясь из делегата. Во многих сценариях этот вариант достаточен. Однако экземпляр задачи, отмененный таким образом, переходит в TaskStatus.RanToCompletion состояние, а не в состояние TaskStatus.Canceled.
Бросив OperationCanceledException и передав ему токен, по которому была запрошена отмена. Предпочтительный способ выполнения — использовать ThrowIfCancellationRequested метод. Задача, отмененная таким образом, переходит в состояние "Отменено", которое вызывающий код может использовать для проверки ответа задачи на запрос на отмену.
В следующем примере показан базовый шаблон отмены задачи, который вызывает исключение:
Замечание
Токен передаётся назначенному пользователем делегату и экземпляру задачи.
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:
try
{
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:
Try
t2.Wait()
Catch e As AggregateException
For Each item In e.InnerExceptions
Console.WriteLine(e.Message & " " & item.Message)
Next
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 .
Возможно, задача может продолжать обрабатывать некоторые элементы после запроса отмены.