2011-06-09 35 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是​​一個嚴肅的事情。