Отмена задач
Классы System.Threading.Tasks.Task и System.Threading.Tasks.Task<TResult> поддерживают отмену с помощью токенов отмены, новшества .NET Framework 4. Дополнительные сведения см. в разделе Отмена. В классах задач отмена включает взаимодействие между пользовательским делегатом, который представляет операцию отмены, и кодом, который запросил отмену. Успешная отмена включает запрашивающий код, вызывающий метод CancellationTokenSource.Cancel, и пользовательский делегат, своевременно завершающий операцию. Операцию можно завершить одним из следующих способов.
Путем простого возврата из делегата. Во многих сценариях этого достаточно, однако экземпляр задачи, отмененный таким образом, переходит в состояние RanToCompletion, а не в состояние Canceled.
Путем создания исключения OperationCanceledException и его передачи в токен, на котором была запрошена отмена. Предпочтительным способом сделать это является использование метода ThrowIfCancellationRequested. Задача, отмененная таким образом, переходит в состояние Canceled, которое вызывающий код может использовать для проверки того, что задача ответила на запрос на отмену.
В следующем примере показан базовый шаблон для отмены задачи, вызвавшей исключение. Обратите внимание, что токен передается пользовательскому делегату и самому экземпляру задачи.
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
End Try
Console.ReadKey()
End Sub
End Module
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
// 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 StartNew.
tokenSource2.Cancel();
// Just continue on this thread, or Wait/WaitAll with try-catch:
try
{
task.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
Console.ReadKey();
}
}
Более полный пример содержится в разделе Практическое руководство. Отмена задачи и ее дочерних элементов.
Когда экземпляр задачи обнаруживает исключение OperationCanceledException, созданное пользовательским кодом, он сравнивает токен исключения со связанным токеном (переданным в API-интерфейс, в котором была создана задача). Если они совпадают и свойство IsCancellationRequested токена возвращает значение true, задача интерпретирует это как подтверждение отмены и переходит в состояние Canceled. Если метод Wait или WaitAll не используется для ожидания задачи, она просто устанавливает состояние Canceled.
Если ожидается задача, которая переходит в состояние Canceled, создается и выдается исключение TaskCanceledException (заключенное в исключение AggregateException). Обратите внимание, что это исключение указывает на успешную отмену, а не на сбой. Следовательно, свойство исключения задачи возвращает значение NULL.
Если свойство IsCancellationRequested токена возвращает значение false или если токен исключения не соответствует токену задачи, исключение OperationCanceledException обрабатывается как обычное исключение, вызывая переход задачи в состояние Faulted. Кроме того, обратите внимание, что наличие других исключений также приведет к переходу задачи в состояние Faulted. Состояние завершения задачи можно получить в свойстве Status.
В некоторых случаях задача может продолжить обработку некоторых элементов после запроса отмены.
См. также
Задачи
Практическое руководство. Отмена задачи и ее дочерних элементов