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 .