0

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

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

ThreadPool.QueueUserWorkItem(delegate

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

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

我的解决方案严重依赖 Castle 作为 DI 框架。我相信我遇到的问题与城堡中的生活方式有关。错误信息是:

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 中正确地创建了线程?

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

4

1 回答 1

3

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

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

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

于 2012-07-03T06:40:50.803 回答