Windsor和ThreadPool.QueueUserWorkItem:“HttpContext.Current为null.PerWebRequestLifestyle只能在ASP.Net中使用”

时间:2012-07-03 06:36:02

标签: asp.net-mvc multithreading asp.net-mvc-3 castle-windsor threadpool

我正在尝试增强in proc MVC缓存以提供旧值,同时触发新线程来填充新值。

如果删除该行,则以下代码“有效”:

ThreadPool.QueueUserWorkItem(delegate

“工作”是指在刷新缓存之前阻止发出触发缓存重新加载的请求的客户端,但所有其他客户端继续加载阴影版本。

理想情况下,我希望在后台进行处理,并且触发缓存刷新的客户端使用该请求的卷影副本。当线程完成后,当他们提出将来的请求时,他们将获得新的缓存值。

我的解决方案在很大程度上依赖于Castle作为DI框架。我相信我遇到的问题是与Castle中的LifeStyles有关。错误消息是:

HttpContext.Current为null。 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中正确创建了线程?

在这种情况下是否有更好的方法来启动线程,这会导致Windsor因PWR生活方式而抛出异常?

1 个答案:

答案 0 :(得分:3)

  

所以我的问题是,我是否在MVC3中正确创建了线程?

不,您在ASP.NET应用程序的后台线程中使用HttpContext.Current。你的问题与Windsor和ASP.NET MVC无关。这只是你不能做的事情,因为后台线程(顾名思义)可以在任何用户HTTP上下文之外的后台运行。因此,尝试在这样的线程中访问此上下文没有任何意义。

由于新的MemoryCache类设计为独立于ASP.NET使用,因此可以使用.NET 4.0中的新缓存功能。