2015-05-19 178 views
12

我有一個asp.net MVC網站,它正在使用其餘api來接收數據。我使用異步任務來執行請求,因爲每個頁面上可能有很多。經過一段時間的正常運行時間,該網站在嘗試接收數據時一直在拋出以下錯誤。調用HttpClient.GetAsync時出錯:底層連接已關閉

底層連接已關閉:發送時發生意外錯誤。

我讀到這可能是由於web.config上的maxconnection設置,但增加這似乎沒有多大區別。

我也使用緩存來減少api上的負載。該任務被緩存,以便稍後可以使用結果。

我發現解決這個問題的唯一方法是通過回收應用程序池。任何幫助,將不勝感激。

/* 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

此錯誤似乎來自IIS。大多數情況下,這是與協議混淆的東西。原因可能是SSL相關或框架兼容性... **幾個問題**:** 1)**您使用SSL嗎? ** 2)**您的應用程序池在IIS中使用什麼版本的.Net? –

+0

感謝您的回覆。是的,我們在網站上使用SSL以及它所連接的網絡服務。應用程序池正在使用.Net v4.0.30319。 – markvpc

+0

檢查您的證書,使用IIS註冊您的證書,檢查綁定。如果一切看起來很好,你甚至可以嘗試刪除並重新註冊證書。我懷疑它被協議搞糊塗了。協議問題導致過度的握手並導致殭屍請求線程。 –

回答

3

這是不對的,

任務被緩存所以結果可以在以後使用。

你應該緩存結果,而不是任務。在第一次執行結束時,您的HttpClient已關閉,當您嘗試檢索緩存的任務時,它將不起作用。

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

謝謝,我會試試這個。有一條線我不得不糾正才能正常工作。返回await Task.FromResult(cachedResult); – markvpc

0

阿卡什可能是對的。 但它似乎或多或少與應用程序池的連接問題。設置連接限制0以使其在應用程序池中不受限制。 有一個finally塊在你的代碼,而被稱爲

gc.collect(); 

垃圾收集方法來刪除未使用的連接,對其他連接空間。

+0

謝謝,應用程序池的連接限制已經設置爲0.我將調查垃圾收集。 – markvpc

相關問題