惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

博客园 - 赏梅斋

直接访问K2数据库找未归档正在进行中的流程的SQL语句 SharePoint学习笔记1--Asp.net与SharePoint的Session机制 安装Lync Server前端必备组件Wmf2008R2时失败的问题 域环境安装SQLServer时出现“帐户名与安全标识之间无任何映射”的问题 网络发现不能启用的问题 sharepoint 2010 与sqlserver denali的支持性安装测试 SPES2011开始注册了! K2 Blackpearl 4.5 怎样配置SQLUM SharePoint2010企业开发最佳实践(九)---- 事件接收器的最佳做法 SharePoint2010企业开发最佳实践(八)---- SPWeb 对象 SharePoint2010企业开发最佳实践(七)---- SPSite 对象 SharePoint2010企业开发最佳实践(五)---- 查找错误释放的对象 SharePoint2010企业开发最佳实践(四)---- 关于使用可释放的 SharePoint 对象的介绍 SharePoint2010企业开发最佳实践(三)---- 对象缓存技术 SharePoint2010企业开发最佳实践(二)---- 处理大型文件夹和列表 SharePoint2010企业开发最佳实践(一)----在 SharePoint Server 中编写有效代码 修改MOSS服务器名称 赏梅斋最新推出论坛Microsoft Information Worker 2008年3月19日主题讨论日
SharePoint2010企业开发最佳实践(六)---- 用于确保释放对象的编码技术
赏梅斋 · 2011-02-11 · via 博客园 - 赏梅斋

可以采用某些编码技术来确保释放对象。这些技术包括在代码中使用以下内容:

  • Dispose 方法

  • using 语句

  • trycatchfinally

Dispose 与 Close 方法的用途

SPWeb 对象和 SPSite 对象的 DisposeClose 方法作用相同。Dispose 方法调用对象的 Close 方法。我们建议调用 Dispose 方法,而不是调用 Close 方法,因为 SPWebSPSite 对象实现 IDisposable 接口,标准 .NET Framework 垃圾收集调用 Dispose 方法从内存中释放与对象关联的任何资源。

using 语句

通过使用 Microsoft Visual C# 和 Visual Basic using 语句,可以自动释放实现 IDisposable 接口的 SharePoint 对象。

以下代码提供了示例。

String str;

using(SPSite oSPsite = new SPSite("http://www.msiw.net/"))
{
  using(SPWeb oSPWeb = oSPSite.OpenWeb())
   {
       str = oSPWeb.Title;
       str = oSPWeb.Url;
   }

利用 using 语句可以大大简化代码。公共语言运行库会将 using 语句转换为 try 和 finally 块,并且会为您释放实现 IDisposable 接口的任何对象。但是,在许多情况下,using 语句并不可取,或者必须慎用并要了解运行库所执行的操作。以下代码示例显示了一个不希望运行库为您构建 finally 块和释放对象的情况。在此情况下,SPContext 返回 SPWeb 对象。

// Do not do this. Dispose() is automatically called on SPWeb.
using( SPWeb web = SPControl.GetContextWeb(HttpContext.Current)) { ... }

SPContext 对象由 SharePoint 框架进行管理并且不应该在代码中明确释放。SPContext.SiteSPContext.Current.SiteSPContext.WebSPContext.Current.Web 返回的 SPSiteSPWeb 对象也是如此。

每当在同一行上合并 SharePoint 对象模型调用时,必须慎重并知道运行库所做的操作。这种情况引发的泄露最难找到。

在以下代码示例中,SPSite 对象会被实例化但不被释放,因为运行库会确保仅释放 OpenWeb 返回的 SPWeb 对象。

void CombiningCallsLeak()
{
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
        // ... New SPSite will be leaked.
    } // SPWeb object web.Dispose() automatically called.
}

通过将一个 using 语句嵌套在另一个语句中,可以解决此问题。

void CombiningCallsBestPractice()
{
    using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        // Perform operations on site.
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

如果不对 SPSite 对象执行任何操作,则可以像在以下代码示例中那样更加简洁地编写此内容。

void CombiningCallsBestPractice()
{
    using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
    using (SPWeb web = siteCollection.OpenWeb())
        {
        // Perform operations on site.
        } // SPWeb object web.Dispose() automatically called; SPSite object
          // siteCollection.Dispose() automatically called.
}

在其他情况下,必须构建自己的 trycatchfinally 块。需要处理异常并因此必须包括 catch 块的情况就是最明显的示例。

try、catch 和 finally 块

每当需要处理异常时,使用 trycatchfinally 块显然是有意义的。try/catch 块中的任何代码都应该具有 finally 控制子句,这样可以确保释放实现 IDisposable 的对象。请注意,在以下代码示例中,应该在 catch 块中填充处理异常的代码。决不要将 catch 块留空。另外请记下在释放之前测试 null 的最佳实践。

String str;
SPSite oSPSite = null;
SPWeb oSPWeb = null;

try
{
   oSPSite = new SPSite("http://server/");
   oSPWeb = oSPSite.OpenWeb(..);

   str = oSPWeb.Title;
}
catch(Exception e)
{
   // Handle exception, log exception, etc.
}
finally
{
   if (oSPWeb != null)
     oSPWeb.Dispose();

   if (oSPSite != null)
      oSPSite.Dispose();
}

foreach 块内创建可释放的对象时,为了避免潜在泄露,必需使用 Tryfinally 块或 using 语句,如以下代码示例中所示。

public static void SPSiteCollectionForEachBestPractice()
{
     string sUrl = "http://www.msiw.net/";
 
      using (SPSite siteCollectionOuter = new SPSite(sUrl))
     {
         SPWebApplication webApp = siteCollectionOuter.WebApplication;
         SPSiteCollection siteCollections = webApp.Sites;

                  SPSite siteCollectionInner = null;
                  foreach (siteCollectionInner in siteCollections)
             {
                      try  // Should be first statement after foreach.
                      {
                          Console.WriteLine(siteCollectionInner.Url);
                          // Exception occurs here.
                      }
                      finally
                      {
                          if(siteCollectionInner != null)
                          siteCollectionInner.Dispose();
                      }
             }
     } // SPSite object siteCollectionOuter.Dispose() automatically called.
 }

Response.Redirect 以及 try 块、catch 块、finally 块和 using 语句

try 块中调用 Response.Redirect 之后,将会执行 finally 块。Response.Redirect 最终会生成 ThreadAbortException 异常。出现此异常时,运行库会执行所有 finally 块,然后结束线程。但是,因为 finally 块可能会执行无限制的计算或取消 ThreadAbortException,所以该线程未必会结束。因此,必须先释放对象,然后才能重定向或传输处理。如果代码必须重定向,请按照与以下代码示例类似的方法来实现代码。

String str;
SPSite oSPSite = null;
SPWeb oSPWeb = null;

try
{
   oSPSite = new SPSite("http://www.msiw.netserver/");
   oSPWeb = oSPSite.OpenWeb(..);

   str = oSPWeb.Title;
   if(bDoRedirection)
   {
       if (oSPWeb != null)
          oSPWeb.Dispose();
   
       if (oSPSite != null)
          oSPSite.Dispose();

       Response.Redirect("newpage.aspx");
   }
}
catch(Exception e)
{
}
finally
{
   if (oSPWeb != null)
     oSPWeb.Dispose();

   if (oSPSite != null)
      oSPSite.Dispose();
}

因为 using 语句会命令运行库创建 finally 块,所以每当在 using 语句内使用 Response.Redirect 时,请确保正确释放对象。以下代码示例演示如何执行此操作。

using (SPSite oSPSite = new SPSite("http://server/"))
using (SPWeb oSPWeb = oSPSite.OpenWeb(..))
{
    if (bDoRedirection)
        Response.Redirect("newpage.aspx");
}

缩短长时间对象保留期的建议

通过遵循以下常规建议,可以缩短 SharePoint 对象的长时间保留期。

  • 如果用 new 运算符创建对象,请确保用于创建的应用程序释放该对象。

良好的编码实践 #1

明确释放

void CreatingSPSiteExplicitDisposeNoLeak()
{
    SPSite siteCollection = null;
    try
    {
        siteCollection = new SPSite("http://www.msiw.net/");
    }
    finally
    {
        if (siteCollection != null)
            siteCollection.Dispose();
    }
}

良好的编码实践 #2

自动释放

CreatingSPSiteWithAutomaticDisposeNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
    } // SPSite object siteCollection.Dispose() is called automatically.
}

释放由返回其他 SPWeb 对象的 SharePoint 方法(如 OpenWeb())所创建的项。

良好的编码实践

void OpenWebNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

  • 不要在线程之间共享任何 SPRequest 对象(以及通过扩展共享任何包含对 SPRequest 对象的引用的对象)。不支持以下性质的任何编码技术:在两个或更多个线程之间共享 SPRequest 对象,或者在一个线程上创建 SPRequest 对象而在另一个线程上释放该对象。这意味着,无法在静态变量中存储任何包含对 SPRequest 对象的引用的对象。因此,不要将实现 IDisposable 的 SharePoint 对象(例如 SPWebSPSite)存储在静态变量中。