官术网_书友最值得收藏!

2.3 對象的釋放

上一節介紹的SPSite和SPWeb對象是開發過程中應用服務器端對象模型操作SharePoint的基礎和入口,幾乎每一次都會用到它們。這兩個對象實現了IDisposable接口(如果對象具有Dispose方法,則意味著實現了IDisposable接口),使用它們時需要注意及時釋放,以防止不再使用的對象堆積在內存而造成異常情況。

這些異常情況包括:

● SharePoint應用程序池頻繁地進行回收,尤其在使用高峰期。

● 應用程序崩潰。

● IIS工作進程W3WP占用的內存異常大。

● 系統和應用程序性能低下。

明確地說,在使用完諸如SPSite、SPWeb這樣的對象后,要及時顯示地釋放她們,而不應依賴垃圾回收器。

2.3.1 如何應用Dispose

如何判定發生了此類異常呢?可以檢查ULS日志(位于C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\LOGS目錄),看看其中是否有與SPRequest對象相關的條目。SharePoint會監視每個特定線程和并行線程中存在的SPRequest對象的數目,并在以下三種情況下向日志中添加有用的條目:

(1)SPRequest對象的總數超出了可配置的閾值。

(2)SPRequest對象在線程結束后繼續存在。

(3)SPRequest對象已通過垃圾收集從堆中移除。

第一種情況是最常發生的,每當SPRequest對象的數目超過網站的閾值時,ULS日志中就會出現以下條目:

● “可能有過量的SPRequest對象(對象數)當前在線程線程號上未得到釋放。請確保正確釋放此對象或其父項(如SPWeb或SPSite對象)。此對象的分配ID為:{GUID}”

如果想增大網站的閾值,可以通過編輯以下注冊表子項來更改此閾值:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared       Tools\Web     Server
Extensions\HeapSettings

LocalSPRequestWarnCount = 所需閾值

在確定可能有該內存問題時,可以通過查找以下兩條消息來確定錯誤釋放的特定實例:

● 在此線程結束之前未釋放SPRequest對象。為了避免浪費系統資源,請在用完此對象或其父項(如SPSite或SPWeb)之后立即將其釋放。現在將釋放此對象。分配ID: {GUID}。要確定在哪里分配了此對象,請在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings處創建注冊表子項。然后在此項下面創建名為SPRequestStackTrace且值為1的新DWORD。

此消息表明SPRequest對象由于在線程結束后仍然存在而被釋放。

● SPRequest對象已被垃圾收集器回收,而不是被明確釋放。為了避免浪費系統資源,請在用完此對象或其父項(如SPSite或SPWeb)之后立即將其釋放。分配ID: {GUID}。要確定在哪里分配了此對象,請在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings處創建注冊表項。然后在此項下面創建名為SPRequestStackTrace且值為1的新DWORD。

此消息表明垃圾收集器釋放了SPRequest對象。

確保釋放的編碼方式有三種:顯示調用Dispose方法、使用using語句塊和使用try、catch和finally語句塊。

顯示調用Dispose方法:web.Dispose();

使用using語句塊:

    using (SPSite site = new SPSite("http://mysiteurl/subsite"))
    {
          using (SPWeb web = site.OpenWeb())
          {
                    //todo
          }
    }

使用try、catch和finally語句塊:

     SPSite site = null;
     SPWeb web = null;
     try
     {
           site = new SPSite("http://server");
           web = site.OpenWeb();
     }
     catch (Exception e)
     {
           //處理發生的異常
     }
     finally
     {
           if (web != null) web.Dispose();
           if (site != null) site.Dispose();
     }

另一方面,對于從上下文(即SPContext)中獲取到的對象是不能進行釋放的,這個會由SharePoint框架自行管理,如果主動釋放會造成異常拋出。這些對象包括:SPContext.Site、SPContext.Current.Site、SPContext.Web和SPContext.Current.Web等。

2.3.2 部分編碼最佳實踐

開發人員應該從平時多多積累最佳實踐的經驗,避免寫出有潛在威脅的代碼。

如果讀者有過一些SharePoint的維護或開發經驗,就會切身感受到有些SharePoint的異常不是特別好處理,一個問題可能有幾種不同的原因導致。因此對于這種可以明確規避的風險,請務必要認真對待,將其克服掉。

下面是關于開發過程中SPSite和SPWeb對象釋放方面最佳實踐的一些說明。

● SPSiteCollection.Add方法將創建并返回新的SPSite實例,需要釋放。

● SPSiteCollection[]索引運算符會針對每次訪問返回一個新的SPSite實例,需要釋放。

● SPSite.AllWebs.Add方法將創建并返回SPWeb實例,需要釋放。

● SPWebCollection.Add方法將創建并返回SPWeb實例,需要釋放。

● SPSite.AllWebs[]索引運算符會在每次訪問對象后返回一個新的SPWeb實例,需要釋放。

● SPSite對象的OpenWeb方法和SelfServiceCreateSite方法將創建SPWeb對象并將其返回給調用方,需要釋放。

● Microsoft.Office.Server.UserProfiles.PersonalSite返回的SPSite對象,需要釋放。

● SPWeb.Webs屬性將返回SPWebCollection對象。需要釋放此集合中的SPWeb對象。

● SPWeb.Webs.Add方法(或SPWebCollection.Add)會創建并返回新的SPWeb對象,需要釋放。

● SPWeb.Webs[]索引運算符會針對每次訪問返回一個新的SPWeb對象,將會通過調用OpenWeb方法來創建SPWeb,需要釋放。

● 如果開發中僅需要獲取網站的信息,可以避免構建SPWeb對象而是使用SPWebCollection的WebsInfo屬性獲取網站集合中各個網站的信息。

主站蜘蛛池模板: 定安县| 宜兰县| 岳阳市| 岑溪市| 土默特右旗| 新平| 行唐县| 肇庆市| 商城县| 古浪县| 克山县| 新巴尔虎右旗| 浮山县| 南岸区| 西峡县| 渭南市| 桑植县| 满洲里市| 凤山市| 忻城县| 武隆县| 新蔡县| 达尔| 遂平县| 吉林市| 茌平县| 瑞安市| 昌邑市| 英山县| 星子县| 桐城市| 喀什市| 黄石市| 黄骅市| 怀柔区| 琼结县| 梓潼县| 铅山县| 阿拉善右旗| 梁山县| 会昌县|