HttpClient - Bir görev iptal edildi mi?


191

Bir veya iki göreviniz olduğunda iyi çalışır, ancak listelenen birden fazla görevimiz olduğunda "Görev iptal edildi" hatası atar.

resim açıklamasını buraya girin

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

İç İstisna ne diyor?
RagtimeWilly

1
Neden CancellationTokenas parametresini alıp kullanmıyorsunuz?
Jim Aho

1
Nedeni HttpClientyanlışlıkla async Task<HttpResponseMessage> Method(){ using(var client = new HttpClient()) return client.GetAsync(request); }
atmaktı

3
HttpClient@JobaDiniz (a ile using()) kullananlar için lütfen durun! Nedeni: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Philippe

Yanıtlar:


274

TaskCanceledExceptionA'nın atılmasının 2 olası nedeni vardır :

  1. Denilen şey Cancel()üzerinde CancellationTokenSourcegörev tamamlamadan önce belirteç iptali ile ilişkili.
  2. İstek zaman aşımına uğradı, yani belirttiğiniz zaman aralığında tamamlanmadı HttpClient.Timeout.

Tahminimce bir zaman aşımı oldu. (Açık bir iptal olsaydı, muhtemelen bunu anlardınız.) İstisnaları inceleyerek daha emin olabilirsiniz:

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
Peki olası bir çözüm nedir? Benzer bir sorunum var. stackoverflow.com/questions/36937328/…
Geliştirici

49
@Dimi - bu oldukça eski, ama kullandığım çözüm Timeout özelliğini daha büyük bir değere ayarlamaktı:httpClient.Timeout = TimeSpan.FromMinutes(30)
RQDQ

2
@RQDQ, siz adamım, adamım! Yapıcıyı kullanmamak sorunu benim için çözdü. Benim özel durumumda, milisaniye içinde bir zaman aşımı istedim. Bir tedavi TimeSpan.FromMilliseconds(Configuration.HttpTimeout)yerine aksine kullanmak new TimeSpan(Configuration.HttpTimeout). Teşekkürler!
Victor Ude

6
@RQDQ httpClient.Timeout = TimeSpan.FromMinutes(30)iyi bir yaklaşım değildir, çünkü belirli bir iş parçacığını 30 dakika boyunca engeller ve ayrıca HTTP bitiş noktasına (ana göreviniz olan) vurmaz . Ayrıca, programınız 30 dakikadan önce biterse, büyük olasılıkla karşılaşma olasılığınız vardır ThreadAbortException. Daha iyi bir yaklaşım, HTTP uç noktasının neden vurulmadığını bulmak, VPN veya bazı sınırlı ağ erişimi gerektirebilir.
Amit Upadhyay

6
@AmitUpadhyay Çağrı awaitdüzenlenirse, iş parçacığı engellenmez. UI iş parçacığı değil, diğer iş parçacığı iş parçacığı iş parçacığı değil, hiçbiri.
Todd Menier

20

Bu sorunla karşılaştım çünkü Main()yöntemim geri dönmeden önce görevin tamamlanmasını beklemiyordu, bu yüzden Task<HttpResponseMessage> myTaskkonsol programımdan çıkıldığında iptal edildi.

Solüsyon aramak oldu myTask.GetAwaiter().GetResult()içinde Main()(gelen bu yanıt ).


9

Başka bir olasılık da sonucun müşteri tarafında beklenmemesidir. Bu, çağrı yığınındaki herhangi bir yöntem, çağrının tamamlanmasını beklemek için await anahtar sözcüğünü kullanmıyorsa oluşabilir.


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

Yukarıdakiler, büyük bir talepte beklemek için en iyi yaklaşımdır. 30 dakika kafanız karıştı; Rastgele zaman ve istediğiniz zaman verebilirsiniz.

Diğer bir deyişle, 30 dakikadan önce sonuç alırsa istek 30 dakika beklemez. 30 dakika, talep işleme süresinin 30 dakika olduğu anlamına gelir. "Görev iptal edildi" hatası veya büyük veri isteği gereksinimleri oluştuğunda.


0

Başka bir neden, hizmeti (API) çalıştırıp hizmete bir kesme noktası (ve kodunuz bazı kesme noktalarına yapışmışsa (örneğin, Visual Studio çözümü Çalışıyor yerine Hata Ayıklama gösteriyorsa )) olabilir. ve daha sonra API'yı istemci kodundan vurmak. Servis kodu bir kesme noktasında duraklatılmışsa, VS'de F5'e basarsınız.


0

Benim durumumda, denetleyici yöntemi zaman uyumsuz olarak yapılmadı ve denetleyici yöntemi içinde çağrılan yöntem zaman uyumsuz oldu.

Bu yüzden bu tür sorunları önlemek için async / en üst seviyeye kadar beklemek önemli.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.