简单的解释,我可以生产:锁定在缓存项的回调和其他方法使用似乎并没有锁定
在我的.NET1.1的Web应用程序创建磁盘上的一个文件,在Render方法,并添加一个项目到缓存过期,比如一分钟。我也有一个回调方法,当缓存项到期时被调用,这会删除由Render创建的文件。在Page_Init方法中,我尝试访问Render方法写入光盘的文件。这两个方法都有一个锁定语句,锁定一个私有静态对象。
意向:
要创建一个网页,其中主要以光盘写入其自身的副本,它被删除之前,它变得太旧(或过期,内容明智的),而服务的文件,如果存在在光盘上。
问题观察:
这实际上是两个问题,我想。请求页面做我期望的事情,它会将页面渲染并立即提供,同时将缓存中的过期条目添加到缓存中。为了测试到期时间是1分钟。
然后我期待60秒后调用回调方法并删除文件。它没有。
再过一分钟(为了参数)我刷新浏览器中的页面。然后我可以看到调用的回调方法,并在锁对象上放置一个锁。 Page_Init也会被调用并在同一个对象上放置一个锁。但是,这两种方法似乎都进入了它们的锁码区块并继续执行。
这导致:渲染检查文件存在,回调方法删除文件,渲染方法尝试服务于现在删除的文件。
可怕地简化代码片段:
public class MyPage : Page
{
private static Object lockObject = new Obect();
protected void Page_Init(...)
{
if (File.Exists(...))
{
lock (lockObject)
{
if (File.Exists(...))
{
Server.Transfer(...);
}
}
}
}
protected override void Render(...)
{
If (!File.Exists(...))
{
// write file out and serve initial copy from memory
Cache.Add(..., new CacheItemRemovedCallback(DoCacheItemRemovedCallback));
}
}
private static void DoCacheItemRemovedCallback(...)
{
lock (lockObject)
{
If (File.Exists(...))
File.Delete(...);
}
}
}
任何人都可以解释这一点,好吗?我知道回调方法本质上是懒惰的,因此只有在发出请求后才会回调,但.NET1.1中的线程当然不会让两个lock()块同时进入?
谢谢,
马特。
不相关,但:在网页上的'private static Object lockObject = new Obect()'?这意味着*所有*请求共享一个锁 - 这是你的意图? – 2009-10-29 12:46:36
也许我没有正确理解这一点,但好像你重复了OutputCache指令的功能?见http://msdn.microsoft.com/en-us/library/hdxfb6cy(VS.71).aspx – PhilPursglove 2009-10-29 13:09:15
[尴尬沉默] 是的,它会出现这样。实际上,我的印象是.NET1.1没有这个功能。我现在要扼杀我的大脑,并试图回忆为什么会这样,以及是否存在1.1 OutputCache中的缺陷。然后我将使用它。 谢谢。 [更多寂静] – 2009-10-29 16:30:09