2011-06-09 47 views
2

我有以下情形:asp.net缓存的多线程锁的webpart

比方说,我们有相同的数据操作两个不同的webpart - 一个是一个饼图,另一种是数据表。 在它们的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部件与另一个Web部件进行通信的最佳方法是什么?“我已经获取数据,所以请等到我将它放入缓存中”?

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

+0

为什么不制作一个静态辅助类? – Earlz 2011-06-09 17:58:30

回答

2

你会想利用lock关键字,以确保数据加载和以原子方式添加到缓存中。

更新:

我修改以保持锁尽可能短访问Cache的例子。代替将数据直接存储在缓存中,代替将被存储。代理将以原子方式创建并添加到缓存中。然后代理将使用自己的锁定来确保数据只加载一次。

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; 
    } 
    } 
} 
+0

我想锁定整个Cache对象吗?另外,如果我使用锁定关键字 - 锁定对象是只写还是读取 - 如果所有其他线程需要等待读取比我正在更改的缓存项目更多的其他缓存项目,我恐怕会损害性能。 – lstanczyk 2011-06-10 16:06:34

+0

是的,你将不得不锁定整个'Cache'对象的访问权限。这将序列化所有的读写操作到'Cache'对象。这将对来自其他线程的读取产生影响。 – 2011-06-10 19:43:12

+0

我修改了代码,使其在更短的时间内保持锁定状态。 – 2011-06-10 20:07:38

0

你可以使用一个互斥体周围的测试Cache["key"]==null

第一个线程获取锁,测试和看见有什么在缓存中,并熄灭获取数据。第二个线程必须等待第一个释放互斥锁。一旦第二个线程进入互斥体,它会测试,看到数据在那里,然后继续。

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

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

1

你为什么不加载数据,并把它在Application_Start在Global.asax中缓存中,然后将需要无锁的,因为锁定Cache是​​一个严肃的事情。