traduccion run cancellationtoken canceled cancel c# .net async-await dotnet-httpclient cancellationtokensource

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 .