2015-05-19 9 views
12

Ich habe eine asp.net MVC-Website, die eine Rest-API verbraucht, um ihre Daten zu erhalten. Ich verwende asynchrone Aufgaben, um die Anfragen auszuführen, da es auf jeder Seite viele geben kann. Nach einer Weile hat die Website den folgenden Fehler ausgelöst, wenn sie versucht hat, Daten zu empfangen.Fehler beim Aufruf von HttpClient.GetAsync: Die zugrunde liegende Verbindung wurde geschlossen

Die zugrunde liegende Verbindung wurde geschlossen: Beim Senden ist ein unerwarteter Fehler aufgetreten.

Ich habe gelesen, dass dies an den Einstellungen für maxconnection in der web.config liegen könnte, aber dies zu erhöhen, scheint keinen großen Unterschied zu machen.

Ich benutze auch Caching, um die Belastung der API zu reduzieren. Die Aufgabe wird zwischengespeichert, sodass das Ergebnis später verwendet werden kann.

Die einzige Möglichkeit, die ich gefunden habe, um dies zu beheben, ist die Wiederverwendung des Anwendungspools. Jede Hilfe wäre willkommen.

/* Code from page_load */ 

var currenciesTask = ApiClient.GetAsync<CurrencyListWrapper>("currencies"); 
var blogArticleTask = ApiClient.GetAsync<BlogArticleListWrapper>("blog/articles", "limit=10"); 
var seoPageTask = ApiClient.GetAsync<SEOPageListWrapper>("seopages"); 

await Task.WhenAll(currenciesTask, blogArticleTask, seoPageTask); 


/* Code from data access later */ 

public class ApiClient : HttpClient 
{ 
    public static Task<T> GetAsync<T>(string operation, string query = null, bool cache = true) 
    { 
    // Check if task is in cache 
    string cacheName = null; 

    if (cache) 
    { 
     cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage()); 

     var cachedTask = HttpRuntime.Cache[cacheName]; 

     if (cachedTask != null) 
     { 
     return (Task<T>)cachedTask; 
     } 

    } 

    // Get data task 
    var task = GetAsyncData<T>(operation, query); 

    // Add to cache if required 
    if (task != null && cache) 
    { 
     App.AddToCache(cacheName, task); 
    } 

    return task; 
    } 

    public static async Task<T> GetAsyncData<T>(string operation, string query = null) 
    { 
    using (ApiClient client = new ApiClient()) 
    { 
     string url; 

     if (query != null) 
     { 
     url = String.Format("{0}?{1}", operation, query); 
     } 
     else 
     { 
     url = String.Format("{0}", operation); 
     } 

     var response = await client.GetAsync(url); 

     return (await response.Content.ReadAsAsync<T>()); 
    } 
    } 
} 
+0

Dieser Fehler scheint von IIS stammen. Meistens ist dies etwas Spezifisches, das mit dem Protokoll kollidiert. Ursachen können SSL-bezogene oder Framework-Kompatibilität sein ... ** Fragen paar **: ** 1) ** verwenden Sie SSL? ** 2) ** Welche Version von .Net verwendet Ihr App-Pool in IIS? –

+0

Danke für die Antwort. Ja, wir verwenden SSL auf der Website und dem Webdienst, mit dem es verbunden ist. Der Anwendungspool verwendet .Net v4.0.30319. – markvpc

+0

Überprüfen Sie Ihr Zertifikat, Ihre Cert-Registrierung bei IIS, überprüfen Sie die Bindungen. Wenn alles in Ordnung ist, können Sie sogar versuchen, Cert zu entfernen und neu zu registrieren. Ich vermute, dass es durch das Protokoll verwirrt ist. Protokollprobleme verursachen übermäßige Handshakes und führen zu Zombies Threads anfragen. –

Antwort

3

Das ist falsch,

Die Aufgabe so das Ergebnis zwischengespeichert wird, kann später verwendet werden.

Sie sollen das Ergebnis zwischenspeichern, nicht die Aufgabe. Am Ende der ersten Ausführung ist Ihre HttpClient geschlossen und wenn Sie versuchen, zwischengespeicherte Aufgabe abzurufen, wird es nicht funktionieren.

public class ApiClient : HttpClient 
{ 
    public static async Task<T> GetAsync<T>(string operation, string query = null, bool cache = true) 
    { 
    // Check if task is in cache 
    string cacheName = null; 

    if (cache) 
    { 
     cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage()); 

     T cachedResult = (T)HttpRuntime.Cache[cacheName]; 

     if (cachedResult!= null) 
     { 
     return Task.FromResult(cachedResult); 
     } 

    } 

    // Get data task 
    var result = await GetAsyncData<T>(operation, query); 

    // Add to cache if required 
    if (result != null && cache) 
    { 
     App.AddToCache(cacheName, result); 
    } 

    return result; 
    } 

    public static async Task<T> GetAsyncData<T>(string operation, string query = null) 
    { 
    using (ApiClient client = new ApiClient()) 
    { 
     string url; 

     if (query != null) 
     { 
     url = String.Format("{0}?{1}", operation, query); 
     } 
     else 
     { 
     url = String.Format("{0}", operation); 
     } 

     var response = await client.GetAsync(url); 

     return (await response.Content.ReadAsAsync<T>()); 
    } 
    } 
} 
+0

Danke, ich werde das versuchen. Es gab eine Zeile, die ich korrigieren musste, um es zum Laufen zu bringen. Rückkehr erwartet Task.FromResult (cachedResult); – markvpc

0

Akash könnte Recht haben. Aber es scheint mehr oder weniger Verbindungsproblem mit Anwendungspool. Legen Sie das Verbindungslimit 0 fest, um es im Anwendungspool unbegrenzt zu machen. Haben ein schließlich in Sie Code zu blockieren, und

gc.collect(); 

Garbage-Collection-Methode aufgerufen werden, nicht verwendete Verbindungen zu entfernen, Platz für andere Verbindung herzustellen.

+0

Danke, das Verbindungslimit für den Anwendungspool ist bereits auf 0 gesetzt. Ich werde die Garbage Collection untersuchen. – markvpc

Verwandte Themen