2009-11-30 30 views
1

我有一個方法(完全服務於請求)的一個簡短的鎖保護部分,使所有初始化(等與日誌相關)。因此,只有1個線程可以在那裏。在本節中,我還會從數據庫加載系統數據(如果未加載)。這自然只在第一次請求時執行,不需要花費時間,並且沒有線程可以傳播,因爲它只執行一次(通過虛擬請求)。在asmx Web服務中爲數據庫IO生成線程的正確方法是什麼?

 
    static public void LoadAllSystemData() 
    { 
     SystemData newData = new SystemData(); //own type (etc. Hashtables in Hashtables). 
     LoadTables(ref newData); 
     LoadClasses(ref newData); 
     LoadAllSysDescrs(ref newData); 
     LoadFatFields(ref newData); 
     LoadAllFields(ref newData); 
     _allData = newData; 
    } 

鎖止守衛部分中的系統數據被從併發線程僅通過讀訪問,並且不需要鎖之後:

 
    static public Hashtable GetTables() 
    { 
     return _allData.Tables; 
    } 

現在鎖保護部必須有方法,如果系統中的數據,檢查比24小時更新並刷新它。如果僅通過調用方法(從鎖保護部分)完成該線程需要很長時間,並且沒有其他線程可以進入鎖保護部分。

 
    static public void CheckStatus() 
    { 
     DateTime timeStamp = DateTime.Now; 
     TimeSpan span = timeStamp.Subtract(_cacheTimeStamp); 
     if (span.Hours >= 24) 
     { 
      LoadAllSystemData(); 
      _cacheTimeStamp = DateTime.Now; 
     } 
    } 

我的問題是:

  1. 如何產卵處理IO所以線程池工作線程可以傳播非線程池線程最好的方式,所有的線程花費最少的時間在鎖保護區?

  2. 是_allData = newData;在LoadAllSystemData原子?如果是這樣,那感覺是最好的實現方式,所以像GetTables這樣的GetXxx方法不需要任何鎖定!

  3. 有什麼辦法可以在請求之前調用LoadAllSystemData?例如在iisreset上?

在此先感謝您的答案!

回答

0

馬蒂,你在問多個問題,指出你的應用程序的最佳結構。我會總結您的問題:

  • 如何在處理任何合法請求之前預加載我的服務所需的數據?
  • 如何確保預加載的數據加載「一次」?
  • 如何按計劃刷新預加載的數據,即每24小時?

瞭解Asp.Net管道和事件結構將幫助您理解這些問題的答案。

首先,Asp.Net管道在Application_Start中提供一次性執行區域。每個應用程序週期會觸發一次。這也會在'iisreset'中觸發,它會循環給定服務器的每個應用程序。但是,應用程序週期本身會根據其配置自行回收。所有這些都通過IIS設置進行控制。

二,Asp.Net是一個請求系統;它不會爲您刷新刷新事件,您也不能將其用作調度程序。你需要一個外部代理人爲你採取行動。

這裏就是你可以做到:

  1. 添加您的預加載的數據例程的Application_Start。
  2. 每24小時配置您的網站的應用程序週期設置。

這將確保您的數據通過Application_Start加載一次。這將確保您的數據在您的網站提供任何請求之前加載。最後,它會確保您的數據每24小時刷新一次。

這是我做:

  1. 添加預加載的數據例程的Application_Start。
  2. 修改預先加載的數據例程以使用Asp.Net緩存,而不是靜態使用。
  3. 修改查找數據以從緩存中檢索數據,並在未找到數據時重新加載。
  4. 爲診斷/監視系統,即nagios提供通過web方法調用異步刷新數據的能力,即「preload_refresh()」。

這將提供與上述解決方案基本相同的轉發效果,但對您的服務具有更好的可靠性。

一如往常,您的里程可能會有所不同。希望這可以幫助。

+0

感謝您的優秀回答。我有一些限制,我不會按照你建議的路徑(關於緩存和權威/監視)。兩者都是我一無所知的東西(現在我做!),也許會用在其他項目。 –

0

無論如何,要回答你的問題的一部分,你可以使用Global.asax中的「Application_Start」方法來執行應用程序啓動時的語句,如果你想在應用程序到來時預先填充數據線上。

+0

你確定嗎?認爲我試過了,但它僅在第一次請求時才執行?但我不能確定... –

+0

並感謝您的回答:) –

+0

當應用程序啓動時,應用程序啓動將觸發,它可能是第一個請求或強制回收。 –

相關問題