0

我正在嘗試增強proc MVC緩存以服務舊值,同時觸發一個新線程來填充新的值。Windsor和ThreadPool.QueueUserWorkItem:「HttpContext.Current爲null。PerWebRequestLifestyle只能在ASP.Net中使用」

這下面的代碼「作品」如果我刪除行:

ThreadPool.QueueUserWorkItem(delegate 

通過「作品」我的意思是指這觸發緩存重新加載請求的客戶機被阻塞,直到刷新緩存,但所有其他客戶端繼續加載影子版本。

理想情況下,我希望在後臺進行處理,並且觸發緩存刷新的客戶端使用該請求的卷影副本。當線程完成後他們發出未來請求時,它們將被提供新的緩存值。

我的解決方案嚴重依賴Castle作爲DI框架。我相信我得到的問題是與Castle中的LifeStyles有關。錯誤消息是:

HttpContext.Current爲空。 PerWebRequestLifestyle只能在ASP.Net

唯一的例外發生在長期運行過程中的深腸子(getCacheItem()),當它試圖解決所需的組件來使用。

我緩存的方法如下:

public T GetShadow<T>(string key, Func<T> getCacheItem, int timeOut) 
{ 
    if (Exists(key)) 
    { 
     _log.Info("Shadow: Returning item from Cache: " + key); 
     return (T)HttpContext.Current.Cache[key]; 
    } 

    var shadowKey = key + "-shadow"; 

    if (Monitor.TryEnter(GetKeyLock(key))) 
    { 
     ThreadPool.QueueUserWorkItem(delegate 
     { 
      try 
      { 
       var item = getCacheItem(); // Long running query 

       // Replace the cache entry 
       HttpRuntime.Cache.Insert(key, item, null, 
            DateTime.UtcNow.AddMinutes(
              timeOut), Cache.NoSlidingExpiration); 

       // And add its shadow for subsequent updates 
       HttpRuntime.Cache.Insert(shadowKey, item, null, 
            DateTime.UtcNow.AddMinutes(timeOut * 2), Cache.NoSlidingExpiration); 
      } 
      finally 
      { 
       Monitor.Exit(GetKeyLock(key)); 
      } 
     }); 
    } 

    while (!Exists(shadowKey)) 
    { 
     Thread.Sleep(500); 
    } 

    return (T)HttpContext.Current.Cache[shadowKey]; 
} 

所以我的問題是,我在做正確內MVC3線程的創建?

有沒有更好的方法在這種情況下啓動一個線程,不會因爲壓水堆的生活方式而導致溫莎發出異常?

回答

2

所以我的問題是,我是否正確地在MVC3內創建線程?

不,您在ASP.NET應用程序的後臺線程中使用HttpContext.Current。你的問題與Windsor和ASP.NET MVC無關。這僅僅是因爲後臺線程(如其名稱所暗示的)可能會在任何用戶HTTP上下文之外的後臺運行而無法完成的。所以試圖在這樣的線程中訪問這個上下文沒有任何意義。

您可以使用.NET 4.0中的新緩存功能,這要歸功於旨在獨立於ASP.NET使用的新類MemoryCache類。

相關問題