run - cancellationtoken c#
Cancelación de una solicitud de HttpClient: ¿Por qué es TaskCanceledException.CancellationToken.IsCancellationRequested false? (1)
Dado el siguiente código:
var cts = new CancellationTokenSource();
try
{
// get a "hot" task
var task = new HttpClient().GetAsync("http://www.google.com", cts.Token);
// request cancellation
cts.Cancel();
await task;
// pass:
Assert.Fail("expected TaskCanceledException to be thrown");
}
catch (TaskCanceledException ex)
{
// pass:
Assert.IsTrue(cts.Token.IsCancellationRequested,
"expected cancellation requested on original token");
// fail:
Assert.IsTrue(ex.CancellationToken.IsCancellationRequested,
"expected cancellation requested on token attached to exception");
}
Esperaría que ex.CancellationToken.IsCancellationRequested sea true dentro del bloque catch, pero no lo es. ¿Estoy malinterpretando algo?
Ese es el caso porque HttpClient internamente (en SendAsync ) está utilizando un TaskCompletionSource para representar la operación async . Devuelve TaskCompletionSource.Task y esa es la tarea que await .
Luego llama a base.SendAsync y registra una continuación en la tarea devuelta que cancela / completa / falla la tarea TaskCompletionSource consecuencia.
En el caso de la cancelación, utiliza TaskCompletionSource.TrySetCanceled que asocia la tarea cancelada con un nuevo CancellationToken ( default(CancellationToken) ).
Puedes verlo mirando la TaskCanceledException . Encima de ex.CancellationToken.IsCancellationRequested ser false ex.CancellationToken.CanBeCanceled también es false , lo que significa que este CancellationToken nunca puede cancelarse, ya que no se creó con una CancellationTokenSource .
En mi opinión, debería usar TaskCompletionSource.TrySetCanceled(CancellationToken) lugar. De esa manera, TaskCompletionSource se asociará con el TaskCompletionSource por el consumidor y no simplemente con el TaskCompletionSource predeterminado. Creo que es un error (aunque menor) y envié un problema al conectarme .