Funciona bem quando há uma ou duas tarefas, porém gera um erro "Uma tarefa foi cancelada" quando temos mais de uma tarefa listada.
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
fonte
fonte
CancellationToken
parâmetro as e não o usa?HttpClient
por engano, por exemploasync Task<HttpResponseMessage> Method(){ using(var client = new HttpClient()) return client.GetAsync(request); }
HttpClient
como @JobaDiniz (com ausing()
), pare! O motivo: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongRespostas:
Existem 2 razões prováveis para que um
TaskCanceledException
seja lançado:Cancel()
noCancellationTokenSource
associado ao token de cancelamento antes da conclusão da tarefa.HttpClient.Timeout
.Meu palpite é que foi um tempo limite. (Se fosse um cancelamento explícito, você provavelmente descobriria isso.) Você pode ter mais certeza inspecionando a exceção:
fonte
httpClient.Timeout = TimeSpan.FromMinutes(30)
TimeSpan.FromMilliseconds(Configuration.HttpTimeout)
em oposição anew TimeSpan(Configuration.HttpTimeout)
trabalhou um tratamento. Obrigado!httpClient.Timeout = TimeSpan.FromMinutes(30)
não é uma boa abordagem, porque bloqueará esse encadeamento específico por 30 minutos e também não atingirá o ponto de extremidade HTTP (que é sua principal tarefa). Além disso, se o seu programa terminar antes de 30 minutos, é mais provável que você encontreThreadAbortException
. Uma abordagem melhor seria descobrir por que esse ponto de extremidade HTTP não está sendo atingido, pode exigir VPN ou algum acesso restrito à rede.await
, nenhum thread será bloqueado. Não é o encadeamento da interface do usuário, não é um encadeamento de conjunto de encadeamentos, outro encadeamento em segundo plano, nenhum.Corri para esse problema porque meu
Main()
método não estava aguardando a conclusão da tarefa antes de retornar, eTask<HttpResponseMessage> myTask
estava sendo cancelado quando meu programa de console foi encerrado.A solução foi chamar
myTask.GetAwaiter().GetResult()
emMain()
(a partir de esta resposta ).fonte
Outra possibilidade é que o resultado não seja esperado no lado do cliente. Isso pode acontecer se qualquer método na pilha de chamadas não usar a palavra-chave wait para aguardar a conclusão da chamada.
fonte
A descrição acima é a melhor abordagem para aguardar uma grande solicitação. Você está confuso cerca de 30 minutos; é hora aleatória e você pode dar o tempo que quiser.
Em outras palavras, a solicitação não aguardará 30 minutos se eles obtiverem resultados antes de 30 minutos. 30 min significa que o tempo de processamento da solicitação é de 30 min. Quando ocorreu o erro "A tarefa foi cancelada" ou requisitos de solicitação de dados grandes.
fonte
Outro motivo pode ser o fato de você estar executando o serviço (API) e colocar um ponto de interrupção no serviço (e seu código ficar travado em algum ponto de interrupção (por exemplo, a solução do Visual Studio está mostrando a Depuração em vez de Executando )). e, em seguida, pressionando a API no código do cliente. Portanto, se o código de serviço estiver em pausa em algum ponto de interrupção, basta pressionar F5 no VS.
fonte
Na minha situação, o método do controlador não foi feito como assíncrono e o método chamado dentro do método do controlador era assíncrono.
Então acho que é importante usar async / wait até o nível superior para evitar problemas como esses.
fonte