asp.net缓存multithreading锁定webparts

我有以下场景:

假设我们有两个不同的webparts在相同的数据上运行 – 一个是饼图,另一个是数据表。 在他们的Page_Load中,他们异步地从数据库加载数据,并在加载时将其放在应用程序缓存中以供进一步使用或由其他Web部件使用。 因此,每个Web部件都有类似于此的代码:

protected void Page_Load(object sender, EventArgs e) { if (Cache["dtMine" + "_" + Session["UserID"].ToString()]==null) { ... Page.RegisterAsyncTask(new PageAsyncTask( new BeginEventHandler(BeginGetByUserID), new EndEventHandler(EndGetByUserID), null, args, true)); } else { get data from cache and bind to controls of the webpart } } 

由于两个webpart都在相同的数据上运行,因此对我来说执行代码两次没有意义。

让一个Web部件与另一个进行通信的最佳方法是什么?“我已经在获取数据,所以只要等到我将其放入缓存”?

我一直在考虑互斥锁,锁定,为缓存项分配临时值并等待临时值更改…许多选项 – 我应该使用哪一个。

您将希望利用lock关键字来确保以primefaces方式加载数据并将其添加到缓存中。

更新:

我修改了示例以保持锁访问Cache尽可能短。 而不是将数据直接存储在缓存中,而是存储代理。 将以primefaces方式创建代理并将其添加到缓存中。 然后代理将使用自己的锁定来确保数据仅加载一次。

 protected void Page_Load(object sender, EventArgs e) { string key = "dtMine" + "_" + Session["UserID"].ToString(); DataProxy proxy = null; lock (Cache) { proxy = Cache[key]; if (proxy == null) { proxy = new DataProxy(); Cache[key] = proxy; } } object data = proxy.GetData(); } private class DataProxy { private object data = null; public object GetData() { lock (this) { if (data == null) { data = LoadData(); // This is what actually loads the data. } return data; } } } 

为什么不加载数据并将其放在Global.asax的Application_Start中的缓存中,因此不需要锁定,因为锁定Cache是​​一件严肃的事情。

您可以在测试Cache["key"]==null周围使用互斥锁:

第一个线程获取锁,测试并发现缓存中没有任何内容,然后关闭以获取数据。 第二个线程必须等待第一个线程释放互斥锁。 一旦第二个线程进入互斥锁,它就会测试,看到数据在那里然后继续。

但这会锁定运行Page_Load()方法的线程 – 可能是一件坏事。

也许更好的解决方案是测试是否已启动提取数据的PageAsyncTask ? 如果没有,请启动它。 如果是这样,你不应该启动另一个,所以你可能想要注册你自己的事件处理程序,以便在它完成时捕获…