Funciona bien cuando tiene una o dos tareas, sin embargo, arroja un error "Se canceló una tarea" cuando tenemos más de una tarea en la lista.
List<Task> allTasks = new List<Task>();
allTasks.Add(....);
allTasks.Add(....);
Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken);
private static Task<T> HttpClientSendAsync<T>(string url, object data, HttpMethod method, string contentType, CancellationToken token)
{
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url);
HttpClient httpClient = new HttpClient();
httpClient.Timeout = new TimeSpan(Constants.TimeOut);
if (data != null)
{
byte[] byteArray = Encoding.ASCII.GetBytes(Helper.ToJSON(data));
MemoryStream memoryStream = new MemoryStream(byteArray);
httpRequestMessage.Content = new StringContent(new StreamReader(memoryStream).ReadToEnd(), Encoding.UTF8, contentType);
}
return httpClient.SendAsync(httpRequestMessage).ContinueWith(task =>
{
var response = task.Result;
return response.Content.ReadAsStringAsync().ContinueWith(stringTask =>
{
var json = stringTask.Result;
return Helper.FromJSON<T>(json);
});
}).Unwrap();
}
c#
task-parallel-library
dotnet-httpclient
Karthikeyan Vijayakumar
fuente
fuente
CancellationToken
parámetro y no lo usas?HttpClient
por error, por ejemploasync Task<HttpResponseMessage> Method(){ using(var client = new HttpClient()) return client.GetAsync(request); }
HttpClient
como @JobaDiniz (con unusing()
), ¡deténgase! La razón: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongRespuestas:
Hay 2 razones probables por las que
TaskCanceledException
se lanzaría un:Cancel()
en elCancellationTokenSource
asociado con el token de cancelación antes de completar la tarea.HttpClient.Timeout
.Supongo que fue un tiempo de espera. (Si se tratara de una cancelación explícita, probablemente lo habría resuelto). Puede estar más seguro al inspeccionar la excepción:
fuente
httpClient.Timeout = TimeSpan.FromMinutes(30)
TimeSpan.FromMilliseconds(Configuration.HttpTimeout)
en lugar denew TimeSpan(Configuration.HttpTimeout)
trabajado un regalo. ¡Gracias!httpClient.Timeout = TimeSpan.FromMinutes(30)
no es un buen enfoque, ya que bloqueará ese hilo en particular durante 30 minutos y tampoco alcanzará el punto final HTTP (que es su tarea principal). Además, si su programa finaliza antes de 30 minutos, es más probable que lo encuentreThreadAbortException
. Un mejor enfoque sería descubrir por qué ese punto final HTTP no está siendo afectado, podría requerir VPN o algún acceso restringido a la red.await
, no se bloquea ningún hilo . No es el subproceso de la interfaz de usuario, no es un subproceso de grupo de subprocesos otro subproceso de fondo, ninguno.Me encontré con este problema porque mi
Main()
método no esperaba que la tarea se completara antes de regresar, por lo queTask<HttpResponseMessage> myTask
se canceló cuando mi programa de consola salió.La solución fue llamar
myTask.GetAwaiter().GetResult()
enMain()
(a partir de esta respuesta ).fuente
Otra posibilidad es que el resultado no sea esperado en el lado del cliente. Esto puede suceder si alguno de los métodos de la pila de llamadas no utiliza la palabra clave wait para esperar a que se complete la llamada.
fuente
Lo anterior es el mejor enfoque para esperar en una solicitud grande. Estás confundido unos 30 minutos; es tiempo aleatorio y puedes dar el tiempo que quieras.
En otras palabras, la solicitud no esperará 30 minutos si obtienen resultados antes de los 30 minutos. 30 minutos significa que el tiempo de procesamiento de la solicitud es de 30 minutos. Cuando se produjo el error "La tarea se canceló", o los requisitos de solicitud de datos de gran tamaño.
fuente
Otra razón puede ser que si está ejecutando el servicio (API) y coloca un punto de interrupción en el servicio (y su código está atascado en algún punto de interrupción (por ejemplo, la solución de Visual Studio muestra Depuración en lugar de Ejecutar )). y luego presionar la API desde el código del cliente. Entonces, si el código de servicio está en pausa en algún punto de interrupción, simplemente presione F5 en VS.
fuente
En mi situación, el método del controlador no se hizo como asíncrono y el método llamado dentro del método del controlador fue asíncrono.
Así que supongo que es importante usar async / wait hasta el nivel superior para evitar problemas como estos.
fuente