HttpClient-작업이 취소 되었습니까?


191

하나 또는 두 개의 작업이있는 경우에는 제대로 작동하지만 둘 이상의 작업이 있으면 "작업이 취소되었습니다"라는 오류가 발생합니다.

여기에 이미지 설명을 입력하십시오

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();
}

내부 예외는 무엇을 말합니까?
RagtimeWilly

1
CancellationToken매개 변수로 사용하고 사용하지 않습니까?
Jim Aho

1
나를 위해 이유는 폐기되었다 HttpClient예를 들어 실수로async Task<HttpResponseMessage> Method(){ using(var client = new HttpClient()) return client.GetAsync(request); }
JobaDiniz

3
HttpClient@JobaDiniz (와 함께 using())를 사용하는 사람들은 중지하십시오! 이유 : aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Philippe

답변:


274

TaskCanceledException발생 하는 데는 두 가지 이유 가 있습니다.

  1. 라는 뭔가 Cancel()CancellationTokenSource작업이 완료되기 전에 토큰 취소와 관련.
  2. 요청 시간이 초과되었습니다. 즉에 지정한 기간 내에 완료되지 않았습니다 HttpClient.Timeout.

내 생각에 그것은 타임 아웃이었다. (명시 적으로 취소 된 경우에는이를 파악했을 것입니다.) 예외를 검사하여보다 확실하게 확인할 수 있습니다.

try
{
    var response = task.Result;
}
catch (TaskCanceledException ex)
{
    // Check ex.CancellationToken.IsCancellationRequested here.
    // If false, it's pretty safe to assume it was a timeout.
}

3
가능한 해결책은 무엇입니까? 비슷한 문제가 있습니다. stackoverflow.com/questions/36937328/…
개발자

49
@Dimi-이것은 꽤 오래되었지만 내가 사용한 솔루션은 Timeout 속성을 더 큰 값으로 설정하는 것이 었습니다.httpClient.Timeout = TimeSpan.FromMinutes(30)
RQDQ

2
@RQDQ, 당신 남자! 생성자를 사용하지 않으면 문제가 해결되었습니다. 필자의 경우에는 밀리 초 단위의 시간 초과를 원했습니다. 치료 TimeSpan.FromMilliseconds(Configuration.HttpTimeout)와는 반대로 사용 new TimeSpan(Configuration.HttpTimeout). 감사!
Victor Ude

6
@RQDQ httpClient.Timeout = TimeSpan.FromMinutes(30)는 30 분 동안 특정 스레드를 차단하고 HTTP 엔드 포인트 (주요 작업)에 도달하지 않기 때문에 좋은 접근 방식이 아닙니다. 또한 프로그램이 30 분 전에 완료되면을 만날 가능성이 큽니다 ThreadAbortException. 더 나은 방법은 HTTP 엔드 포인트에 도달하지 않은 이유를 찾는 것입니다. VPN 또는 일부 제한된 네트워크 액세스가 필요할 수 있습니다.
Upadhyay

6
통화가되는 @AmitUpadhyay 경우 await에드, 다음 더 스레드가 차단되지 않습니다. UI 스레드가 아니며 스레드 풀 스레드가 아닌 다른 백그라운드 스레드가 없습니다.
Todd Menier

20

Main()메서드가 반환하기 전에 작업이 완료되기를 기다리지 않았기 때문에이 문제가 발생 하여 Task<HttpResponseMessage> myTask콘솔 프로그램이 종료 될 때 취소되었습니다.

해결책은 ( 이 답변에서 ) 전화하는 것 myTask.GetAwaiter().GetResult()입니다 .Main()


9

또 다른 가능성은 결과가 클라이언트 측에서 기다리지 않을 수 있습니다. 호출 스택의 한 메소드가 await 키워드를 사용하여 호출이 완료되기를 기다리지 않는 경우에 발생할 수 있습니다.


8
var clientHttp = new HttpClient();
clientHttp.Timeout = TimeSpan.FromMinutes(30);

위는 큰 요청을 기다리는 가장 좋은 방법입니다. 약 30 분 동안 혼란스러워합니다. 그것은 임의의 시간이며 원하는 시간을 줄 수 있습니다.

즉, 요청이 30 분 전에 결과를 얻는 경우 30 분 동안 기다리지 않습니다. 30 분은 요청 처리 시간이 30 분임을 의미합니다. "작업이 취소되었습니다"오류 또는 큰 데이터 요청 요구 사항이 발생한 경우


0

또 다른 이유는 서비스 (API)를 실행 중이고 서비스에 중단 점을두고있는 경우 코드가 일부 중단 점에 멈춰있는 경우 일 수 있습니다 (예 : Visual Studio 솔루션 에 Running 대신 디버깅이 표시됨). 그런 다음 클라이언트 코드에서 API를 누르십시오. 따라서 서비스 코드가 중단 점에서 일시 중지되면 VS에서 F5를 누르십시오.


0

내 상황에서 컨트롤러 메서드는 비동기식으로 만들어지지 않았으며 컨트롤러 메서드 내에서 호출 된 메서드는 비동기식이었습니다.

따라서 이와 같은 문제를 피하기 위해 async / await를 최상위 레벨까지 사용하는 것이 중요하다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.