Aşağıdaki kod, iptal edilmekte olan bir görev oluşturur. await
İfadesi (durum 1), Wait()
(durum 2) System.Threading.Tasks.TaskCanceledException
(System.AggregateException
içinde sarılmış) atarken System.OperationCanceledException
'u atar.OperationCanceledException VS GörevKanceledException Görev iptal edildiğinde
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Program.MainAsync().Wait();
}
private static async Task MainAsync()
{
using(var cancellationTokenSource = new CancellationTokenSource())
{
var token = cancellationTokenSource.Token;
const int cancelationCheckTimeout = 100;
var task = Task.Run(
async() =>
{
for (var i = 0; i < 100; i++)
{
token.ThrowIfCancellationRequested();
Console.Write(".");
await Task.Delay(cancelationCheckTimeout);
}
},
cancellationTokenSource.Token
);
var cancelationDelay = 10 * cancelationCheckTimeout;
cancellationTokenSource.CancelAfter(cancelationDelay);
try
{
await task; // (1)
//task.Wait(); // (2)
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine($"Task.IsCanceled: {task.IsCanceled}");
Console.WriteLine($"Task.IsFaulted: {task.IsFaulted}");
Console.WriteLine($"Task.Exception: {((task.Exception == null) ? "null" : task.Exception.ToString())}");
}
}
}
}
Durum 1 çıkışı:
..........System.OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowIfCancellationRequested()
at Program.<>c__DisplayClass1_0.<<MainAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Program.<MainAsync>d__1.MoveNext()
Task.IsCanceled: True
Task.IsFaulted: False
Task.Exception: null
Durum 2 çıkışı:
..........System.AggregateException: One or more errors occurred. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at Program.<MainAsync>d__1.MoveNext()
---> (Inner Exception #0) System.Threading.Tasks.TaskCanceledException: A task was canceled.<---
Task.IsCanceled: True
Task.IsFaulted: False
Task.Exception: null
Neden System.AggregateException
2 durumda bir iç durum olarak System.OperationCanceledException
içermiyor?
Ben ThrowIfCancellationRequested()
OperationCanceledException
atar biliyoruz ve biz Task
iptal (arızalı değil) durumuna alır her iki durumda da görebiliriz.
.NET API bir yöntem iptal her iki durumda da tutarlı davranış üretir, çünkü bu Kafamı kurcalayan - iptal edilen görev sadece TaskCanceledException
atar:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Program.MainAsync().Wait();
}
private static async Task MainAsync()
{
using(var cancellationTokenSource = new CancellationTokenSource())
{
var token = cancellationTokenSource.Token;
var task = Task.Delay(1000, token);
cancellationTokenSource.CancelAfter(100);
try
{
await task; // (1)
//task.Wait(); // (2)
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine($"Task.IsCanceled: {task.IsCanceled}");
Console.WriteLine($"Task.IsFaulted: {task.IsFaulted}");
Console.WriteLine($"Task.Exception: {((task.Exception == null) ? "null" : task.Exception.ToString())}");
}
}
}
}
Durum 1 çıkış:
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Program.<MainAsync>d__1.MoveNext()
Task.IsCanceled: True
Task.IsFaulted: False
Task.Exception: null
Durum 2 çıkışı:
System.AggregateException: One or more errors occurred. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at Program.<MainAsync>d__1.MoveNext()
---> (Inner Exception #0) System.Threading.Tasks.TaskCanceledException: A task was canceled.<---
Task.IsCanceled: True
Task.IsFaulted: False
Task.Exception: null
Önemli mi? 'TaskCanceledException' türetilmiş bir“ OperationCanceledException ”sınıfıdır, bu yüzden eğer yakaladıysanız (OperationCanceledException e), her iki istisna tipini de yakalarsınız. Kaydettiğiniz tek bilgi parçası 'TaskCanceledException.Task' özelliği. –
Katılıyorum ama daha önce “OperationCanceledException” var iken “TaskCanceledException” ın tanıtımı/kullanımı nedenlerini merak ettim. –
Bunu tanıtmanın nedeni, bazı durumlarda, Görev'i içeren daha türetilmiş formları atabileceğiniz durumlarda iptal edilen Görev bağlamını yakalayabilmenizdir.'ThrowIfCancellationRequested' genel olarak yazılmıştır, bir Görev'in içinde olduğunu bilmez, bu nedenle Görev özelliği olmadan daha genel bir istisna ortaya çıkarır. –