Compartir a través de


Eliminación de objetos

Última modificación: jueves, 08 de abril de 2010

Hace referencia a: SharePoint Foundation 2010

En este artículo
Introducción al uso de objetos descartables de SharePoint
Búsqueda de objetos eliminados incorrectamente
Técnicas de codificación para garantizar la eliminación de objetos
Objetos SPSite
Objetos SPWeb
Otros objetos que requieren eliminación
Conclusión

Introducción al uso de objetos descartables de SharePoint

Los objetos de los modelos de objetos de Microsoft SharePoint Foundation 2010 y Microsoft SharePoint Server 2010 actúan como una interfaz para trabajar con datos de SharePoint Foundation. Con frecuencia, los programadores llaman al modelo de objetos para leer datos desde o escribir nuevos datos en los almacenes de datos de SharePoint Foundation 2010 y SharePoint Server 2010.

Los modelos de objetos de SharePoint Foundation 2010 y SharePoint Server 2010 contienen objetos que implementan la interfaz IDisposable. Debe tomar precauciones al usar estos objetos para evitar su retención a largo plazo en la memoria en Microsoft .NET Framework.

En concreto, debe eliminar explícitamente los objetos de SharePoint que implementan IDisposable cuando haya terminado de usarlos.

En escenarios en los que usa muchos objetos de SharePoint (por ejemplo, en sitios de SharePoint que usan elementos web personalizados), se pueden ocasionar los siguientes comportamientos inusuales si no elimina los objetos de SharePoint cuando haya terminado de usarlos.

  • Reciclajes frecuentes del grupo de aplicaciones de SharePoint Foundation, especialmente durante los períodos de mayor uso

  • Bloqueos de aplicaciones que aparecen como daños en el montón en el depurador

  • Uso intensivo de memoria para procesos de trabajo de Internet Information Services (IIS)

  • Rendimiento deficiente del sistema y aplicaciones

En este artículo se proporciona una guía sobre los procedimientos adecuados para la manipulación y eliminación de objetos de SharePoint que implementan IDispose. Los temas tratados en este artículo también los marca SharePoint Dispose Checker Tool, un programa gratuito disponible como descarga, que inspecciona los ensamblados en busca de prácticas de codificación que puedan causar pérdidas de memoria debido al tratamiento o eliminación incorrectos de objetos de SharePoint.

¿Por qué eliminar?

Muchos de los objetos de SharePoint Foundation, principalmente los objetos de las clases SPSite y SPWeb, se crean como objetos administrados. Sin embargo, estos objetos usan código y memoria no administrados para realizar la mayor parte de su trabajo. La parte administrada del objeto es mucho menor que la parte no administrada. Debido a que la parte más pequeña administrada no realiza una demanda intensiva de memoria al recolector de elementos no utilizados, éste no libera el objeto de la memoria a tiempo. El uso que hace el objeto de una gran cantidad de memoria no administrada puede provocar algunos de los comportamientos inusuales descritos anteriormente. Si llama a aplicaciones que trabajan con objetos IDisposable en SharePoint Foundation debe eliminar los objetos cuando las aplicaciones hayan terminado de usarlos. No debe confiar en el recolector de elementos no utilizados para que los libere de la memoria automáticamente.

Búsqueda de objetos eliminados incorrectamente

Para identificar la posible presencia de objetos eliminados incorrectamente realice las siguientes preguntas:

  1. ¿El grupo de aplicaciones se recicla con frecuencia, especialmente con cargas elevadas (suponiendo que el grupo de aplicaciones está configurado para reciclarse cuando se alcanza un umbral de memoria)?

    El umbral de memoria debería estar entre 800 megabytes (MB) y 1,5 gigabytes (GB), suponiendo que hay al menos 2 GB de RAM. Si se configura el reciclaje del grupo de aplicaciones para que tenga lugar cuando el uso de memoria esté más cerca de 1 GB, se obtendrán mejores resultados; pero debería realizar pruebas para determinar qué configuración es mejor para su entorno. Si la configuración de reciclaje es demasiado baja, el sistema tendrá problemas de rendimiento debido a que el grupo de aplicaciones se reciclará muy frecuentemente. Si el valor es demasiado alto, el sistema experimentará problemas de rendimiento debido a intercambios de página, fragmentación de memoria y otros problemas.

  2. ¿El sistema tiene un rendimiento deficiente, especialmente con cargas elevadas?

    A medida que el uso de memoria comienza a aumentar, el sistema debe compensar, por ejemplo, mediante memoria de paginación y controlando la fragmentación de memoria.

  3. ¿El sistema se bloquea o los usuarios experimentan errores inesperados tales como tiempos de espera o errores de páginas no disponibles, especialmente con cargas elevadas?

    Nuevamente, cuando el uso de memoria aumenta o se fragmenta, se producen errores en algunas funciones porque no pueden asignar memoria para otras operaciones. En muchos casos, el código no controla adecuadamente la excepción "memoria insuficiente", lo que provoca errores falsos o engañosos.

  4. ¿Su sistema usa elementos web personalizados o de terceros, o aplicaciones personalizadas?

    Es posible que no sepa que estos elementos web deben eliminar objetos de SharePoint ni por qué deben hacerlo, y que suponga que la recolección de elementos no utilizados realiza esta función automáticamente. Sin embargo, esto no sucede así en todos los casos.

Si la respuesta a la pregunta número 4 y a una o más de las otras preguntas es "sí", es muy probable que el código personalizado no esté eliminando los elementos correctamente.

Si los sitios muestran alguno de los comportamientos inusuales descritos anteriormente, puede determinar si la causa es una pérdida de memoria debida a los objetos eliminados incorrectamente al comprobar si los registros ULS (disponibles en C:\Program Files\Common Files\microsoft shared\Web Server Extensions\14\LOGS) tienen entradas relacionadas con el objeto SPRequest. Cada instancia de SPSite y SPWeb contiene una referencia a un objeto SPRequest que, a su vez, contiene una referencia a un objeto COM no administrado que controla la comunicación con el servidor de bases de datos. SharePoint Foundation supervisa el número de objetos SPRequest que existen en cada subproceso específico y en subprocesos paralelos, y agrega entradas útiles a los registros en los siguientes tres escenarios:

  • El número total de objetos SPRequest supera un umbral configurable.

  • Un objeto SPRequest continúa existiendo al final de un subproceso.

  • La recolección de objetos no utilizados quitó un objeto SPRequest del montón.

El primer escenario se produce con más frecuencia, especialmente si el sitio usa el valor de umbral predeterminado de ocho objetos SPRequest. Cuando el número de objetos SPRequest supera este umbral, la siguiente entrada aparece en los registros ULS:

"Número posiblemente excesivo de objetos SPRequest (número de objetos) actualmente sin liberar en el subproceso número de subproceso. Asegúrese de que este objeto o su elemento primario (como un objeto SPWeb o SPSite) se elimine apropiadamente. Identificador de asignación para este objeto: {GUID}"

El mejor umbral varía según la naturaleza de su sitio y las aplicaciones que se ejecutan en él. Cuando los sitios tienen problemas de rendimiento, debe supervisar los registros ULS de la instalación para saber cuántos objetos SPRequest están creando las aplicaciones del sitio. Esto ayuda a determinar si los diseños de los sitios y aplicaciones están creando demasiados objetos SPRequest. Incluso si la eliminación incorrecta de objetos no es la causa del problema de rendimiento, es posible que deba rediseñar los sitios o aplicaciones de sitio personalizadas para reducir el consumo de memoria global causado por la proliferación excesiva de objetos SPRequest.

Debido a que el umbral predeterminado muy bajo no se aplica a muchos sitios, puede cambiar este umbral mediante la edición de la siguiente subclave del Registro:

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

LocalSPRequestWarnCount = valor de umbral deseado

Después de determinar que la eliminación incorrecta de objetos podría estar provocando la proliferación de objetos SPRequest y aumentando innecesariamente el consumo de memoria de los sitios, puede encontrar instancias específicas de eliminación incorrecta mediante la búsqueda de las siguientes dos entradas. Ambos mensajes indican casos en los que se desperdicia memoria debido a la eliminación incorrecta de objetos de SharePoint y ambos se relacionan con el número y el estado de objetos SPRequest en un único subproceso:

  • "Un objeto SPRequest no se eliminó antes del final de este subproceso. Para no desperdiciar recursos del sistema, elimine este objeto o su elemento primario (como SPSite o SPWeb) ni bien haya terminado de usarlo. Este objeto se eliminará ahora. Identificador de asignación: {GUID}. Para determinar dónde se ha asignado este objeto, cree una subclave del Registro en HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings. A continuación, cree un nuevo valor DWORD denominado SPRequestStackTrace con el valor 1 bajo esta clave".

    Este mensaje indica que se ha eliminado un objeto SPRequest porque aún existía al final de un subproceso.

  • "El recolector de elementos no utilizados recuperó un objeto SPRequest en lugar de liberarlo explícitamente. Para no desperdiciar recursos del sistema, elimine este objeto o su elemento primario (como SPSite o SPWeb) ni bien haya terminado de usarlo. Identificador de asignación: {GUID}. Para determinar dónde se ha asignado este objeto, cree una clave del Registro en HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings. A continuación, cree un nuevo valor DWORD denominado SPRequestStackTrace con el valor 1 bajo esta clave".

    Este mensaje indica que el recolector de elementos no utilizados eliminó un objeto SPRequest.

Para identificar el código que causa el problema, puede buscar en los registros entradas que contengan los identificadores de asignación, o seguir las instrucciones que aparecen en las advertencias y agregar el siguiente valor de configuración de subclave al Registro:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings SPRequestStackTrace = 1

Este valor de configuración de subclave garantiza que el seguimiento de la pila de la asignación original de SPRequest (que se produce siempre que se crea un objeto SPSite o SPWeb) se agregue a los registros cuando se produzcan estas advertencias.

En las secciones siguientes se describen varias técnicas de codificación que puede usar para garantizar que los objetos se eliminen correctamente.

Técnicas de codificación para garantizar la eliminación de objetos

Puede emplear determinadas técnicas de codificación para garantizar la eliminación de objetos. Estas técnicas incluyen el uso de los siguientes elementos en el código:

  • El método Dispose

  • La instrucción using

  • Los bloques try, catch y finally

Uso de los métodos Dispose y Close

Los métodos Dispose y Close para los objetos SPWeb y SPSite funcionan de la misma manera. El método Dispose llama al método Close del objeto. Se recomienda llamar al método Dispose, en lugar de Close, porque los objetos SPWeb y SPSite implementan la interfaz IDisposable y la recolección de elementos no utilizados estándar de .NET Framework llama al método Dispose para liberar de la memoria los recursos asociados con el objeto.

La instrucción using

Puede eliminar automáticamente objetos de SharePoint que implementan la interfaz IDisposable mediante la instrucción using de Microsoft Visual C# y Visual Basic.

El código siguiente proporciona un ejemplo.

String str;

using(SPSite oSPsite = new SPSite("https://server"))
{
  using(SPWeb oSPWeb = oSPSite.OpenWeb())
   {
       str = oSPWeb.Title;
       str = oSPWeb.Url;
   }
}  
Dim str As String

Using oSPsite As New SPSite("https://server")
  Using oSPWeb As SPWeb = oSPSite.OpenWeb()
     str = oSPWeb.Title
     str = oSPWeb.Url
  End Using
End Using

Puede simplificar en gran medida el código si aprovecha las instrucciones using. Como se indicó en la Referencia de C# (en el tema sobre la instrucción using), Common Language Runtime convierte las instrucciones using en bloques try and finally y se eliminan los objetos que implementan la interfaz IDisposable. Sin embargo, en muchos casos no se recomienda el uso de instrucciones using o se deben usar con precaución y comprendiendo lo que hace el tiempo de ejecución. En el siguiente ejemplo de código, se muestra un caso en el que no es deseable que el tiempo de ejecución construya un bloque finally y elimine objetos. En este caso, SPContext devuelve un objeto SPWeb.

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

SharePoint Framework administra los objetos SPContext y no se deben eliminar explícitamente en el código. Esto ocurre también con los objetos SPSite y SPWeb que devuelven SPContext.Site, SPContext.Current.Site, SPContext.Web y SPContext.Current.Web.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_220.

Debe tener precaución y ser consciente de lo que hace el tiempo de ejecución cada vez que se combinan llamadas al modelo de objetos de SharePoint en la misma línea. Las pérdidas que surgen en este escenario se encuentran entre las más difíciles de encontrar.

En el ejemplo de código siguiente, se crea una instancia de un objeto SPSite pero no se elimina, porque el tiempo de ejecución solamente garantiza la eliminación del objeto SPWeb que devuelve OpenWeb.

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

Para corregir este problema, anide una instrucción using dentro de otra.

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.
}
Private Sub CombiningCallsBestPractice()
    Using siteCollection As New SPSite(SPContext.Current.Web.Url)
        Using web As SPWeb = siteCollection.OpenWeb()
            ' Perform operations on site.
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Si no realiza ninguna operación en el objeto SPSite, podría escribir esto más brevemente, como en el siguiente ejemplo de código.

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.
}
Private Sub CombiningCallsBestPractice()
    Using siteCollection As New SPSite(SPContext.Current.Web.Url)
        Using web As SPWeb = siteCollection.OpenWeb()
            ' Perform operations on site.
        End Using ' SPWeb object web.Dispose() automatically called; SPSite object
    End Using
    ' siteCollection.Dispose() automatically called.
End Sub

En otros casos, debe construir sus propios bloques try, catch y finally. Los ejemplos más obvios son escenarios en los que debe controlar excepciones y, por lo tanto, debe incluir un bloque catch. En la siguiente sección se proporcionan instrucciones acerca de cuándo y cómo usar los bloques try, catch y finally.

Los bloques try, catch y finally

El uso de los bloques try, catch y finally tiene sentido cuando debe controlar excepciones. Cualquier código dentro de un bloque try/catch debe tener una cláusula finally que rija, que garantice que se eliminen los objetos que implementan IDisposable. Observe que en el siguiente ejemplo de código debe rellenar el bloque catch con código que controla la excepción. Nunca deje vacío un bloque catch. Tenga en cuenta también el procedimiento recomendado para comprobación de null antes de la eliminación.

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

try
{
   oSPSite = new SPSite("https://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();
}
Dim str As String
Dim oSPSite As SPSite = Nothing
Dim oSPWeb As SPWeb = Nothing

Try
   oSPSite = New SPSite("https://server")
   oSPWeb = oSPSite.OpenWeb(..)

   str = oSPWeb.Title
Catch e As Exception
' Handle exception, log exception, etc.
Finally
   If oSPWeb IsNot Nothing Then
 oSPWeb.Dispose()
   End If

   If oSPSite IsNot Nothing Then
  oSPSite.Dispose()
   End If
End Try

Se necesitarían los bloques Try y finally o una instrucción using para evitar posibles pérdidas cuando crea un objeto descartable dentro de un bloque foreach, como se muestra en el siguiente ejemplo de código.

public static void SPSiteCollectionForEachBestPractice()
{
     string sUrl = "http://spvm";
 
      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.
 }
Public Shared Sub SPSiteCollectionForEachBestPractice()
    Dim sUrl As String = "http://spvm"

    Using siteCollectionOuter As New SPSite(sUrl)
        Dim webApp As SPWebApplication = siteCollectionOuter.WebApplication
        Dim siteCollections As SPSiteCollection = webApp.Sites

        Dim siteCollectionInner As SPSite = Nothing
        For Each siteCollectionInner In siteCollections
            Try ' Should be first statement after foreach.
                Console.WriteLine(siteCollectionInner.Url)
                ' Exception occurs here.
            Finally
                If siteCollectionInner IsNot Nothing Then
                    siteCollectionInner.Dispose()
                End If
            End Try
        Next
    End Using
End Sub ' SPSite object siteCollectionOuter.Dispose() automatically called.

Response.Redirect con los bloques try, catch y finally, e instrucciones using

El bloque finally se ejecuta después de llamar a Response.Redirect en el bloque try. Response.Redirect, en última instancia, genera una excepción ThreadAbortException. Cuando se genera esta excepción, el tiempo de ejecución ejecuta todos los bloques finally antes de terminar el subproceso. Sin embargo, debido a que el bloque finally puede realizar una cantidad ilimitada de operaciones o cancelar ThreadAbortException, el subproceso no necesariamente finalizará. Por lo tanto, para que pueda tener lugar cualquier redirección o la transferencia de procesamiento, debe eliminar los objetos. Si el código debe realizar una redirección, impleméntelo de forma similar al siguiente ejemplo de código.

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

try
{
   oSPSite = new SPSite("https://server");
   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();
}
Dim str As String
Dim oSPSite As SPSite = Nothing
Dim oSPWeb As SPWeb = Nothing

Try
   oSPSite = New SPSite("https://server")
   oSPWeb = oSPSite.OpenWeb(..)

   str = oSPWeb.Title
   If bDoRedirection Then
         If oSPWeb IsNot Nothing Then
                 oSPWeb.Dispose()
         End If
         If oSPSite IsNot Nothing Then
              oSPSite.Dispose()
         End If

         Response.Redirect("newpage.aspx")
   End If
Catch e As Exception
Finally
   If oSPWeb IsNot Nothing Then
         oSPWeb.Dispose()
   End If

   If oSPSite IsNot Nothing Then
         oSPSite.Dispose()
   End If
End Try

Debido a que una instrucción using indica al tiempo de ejecución que cree un bloque finally, cuando usa Response.Redirect de una instrucción using, asegúrese de que los objetos se eliminan correctamente. En el ejemplo de código siguiente se muestra cómo hacerlo.

using (SPSite oSPSite = new SPSite("https://server"))
using (SPWeb oSPWeb = oSPSite.OpenWeb(..))
{
    if (bDoRedirection)
        Response.Redirect("newpage.aspx");
}
Using oSPSite As New SPSite("https://server")
    Using oSPWeb As SPWeb = oSPSite.OpenWeb(..)
        If bDoRedirection Then
            Response.Redirect("newpage.aspx")
        End If
    End Using
End Using

Recomendaciones para reducir la retención a largo plazo de objetos

Para reducir la retención a largo plazo de objetos de SharePoint, siga estas recomendaciones generales.

  • Si crea el objeto con un operador new, asegúrese de que la aplicación de creación lo elimine.

    Nota

    Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_110.

    Procedimiento recomendado de codificación nº 1

    Eliminación explícita

    void CreatingSPSiteExplicitDisposeNoLeak()
    {
        SPSite siteCollection = null;
        try
        {
            siteCollection = new SPSite("http://moss");
        }
        finally
        {
            if (siteCollection != null)
                siteCollection.Dispose();
        }
    }
    
    Private Sub CreatingSPSiteExplicitDisposeNoLeak()
        Dim siteCollection As SPSite = Nothing
        Try
            siteCollection = New SPSite("http://moss")
        Finally
            If siteCollection IsNot Nothing Then
                siteCollection.Dispose()
            End If
        End Try
    End Sub
    

    Procedimiento recomendado de codificación nº 2

    Eliminación automática

    CreatingSPSiteWithAutomaticDisposeNoLeak()
    {
        using (SPSite siteCollection = new SPSite("http://moss"))
        {
        } // SPSite object siteCollection.Dispose() is called automatically.
    }
    
    CreatingSPSiteWithAutomaticDisposeNoLeak()
    {
        using (SPSite siteCollection = new SPSite("http://moss"))
        {
        } // SPSite object siteCollection.Dispose() is called automatically.
    }
    
  • Eliminación de elementos creados por los métodos de SharePoint que devuelven otros objetos SPWeb (como OpenWeb()).

    Nota

    Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_120.

    Procedimiento recomendado de codificación

    void OpenWebNoLeak()
    {
        using (SPSite siteCollection = new SPSite("http://moss"))
        {
            using (SPWeb web = siteCollection.OpenWeb())
            {
            } // SPWeb object web.Dispose() automatically called.
        }  // SPSite object siteCollection.Dispose() automatically called.
    }
    
    Private Sub OpenWebNoLeak()
            Using siteCollection As New SPSite("http://moss")
                    Using web As SPWeb = siteCollection.OpenWeb()
                    End Using ' SPWeb object web.Dispose() automatically called.
            End Using ' SPSite object siteCollection.Dispose() automatically called.
    End Sub
    
  • No comparta ningún objeto SPRequest (y por consiguiente, ningún objeto que contenga una referencia a un objeto SPRequest) entre subprocesos. Las técnicas de codificación que comparten un objeto SPRequest entre dos o más subprocesos o crean un objeto SPRequest en un subproceso y lo eliminan en otro, no son compatibles. Esto significa que no se pueden almacenar objetos que contengan una referencia a un objeto SPRequest en una variable estática. Por lo tanto, no se deben almacenar objetos de SharePoint que implementan IDisposable (por ejemplo, SPWeb o SPSite) en variables estáticas.

Objetos SPSite

En esta sección se describen situaciones en las que se devuelven nuevos objetos SPSite y deben eliminarse.

En general, cada vez que una aplicación de llamada usa los nuevos constructores SPSite (cualquier firma), debería llamar al método Dispose() cuando haya terminado de usar el objeto. Si el objeto SPSite se obtiene de GetContextSite(), la aplicación de llamada no debe eliminar el objeto. Debido a que los objetos SPWeb y SPSite mantienen una lista interna que se deriva de este modo, la eliminación del objeto puede hacer que el modelo de objetos de SharePoint se comporte de manera inesperada. Internamente, SharePoint Foundation enumera esta lista una vez que se haya completado la página para eliminar los objetos correctamente.

Clase SPSiteCollection

En esta sección se describen los métodos, propiedades u operadores del objeto SPSiteCollection que requieren que se cierre el objeto devuelto SPSite después de obtener acceso.

Método SPSiteCollection.Add

El método SPSiteCollection.Add crea y devuelve un nuevo objeto SPSite. Debería eliminar los objetos SPSite devueltos desde el método SPSiteCollection.Add.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_240.

Procedimiento no recomendado de codificación

void SPSiteCollectionAddLeak()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;
    SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User", 
      "roger.lamb@litwareinc.com");
    // SPSite siteCollection leak.
}
Private Sub SPSiteCollectionAddLeak()
        Dim webApp As SPWebApplication = New SPSite("http://moss").WebApplication
        Dim siteCollections As SPSiteCollection = webApp.Sites
        Dim siteCollection As SPSite = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\User", "roger.lamb@litwareinc.com")
        ' SPSite siteCollection leak.
End Sub

Procedimiento recomendado de codificación

void SPSiteCollectionAddNoLeak()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;
    using (SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User", 
      "roger.lamb@litwareinc.com"))
    {
    } // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub SPSiteCollectionAddNoLeak()
      Dim webApp As SPWebApplication = New SPSite("http://moss").WebApplication
      Dim siteCollections As SPSiteCollection = webApp.Sites
      Using siteCollection As SPSite = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\User", "roger.lamb@litwareinc.com")
      End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Operador de índice SPSiteCollection [ ]

El operador de índice SPSiteCollection [] devuelve un nuevo objeto SPSite para cada acceso. Incluso si ya se ha obtenido acceso a ese objeto, se crea una instancia de SPSite. En los ejemplos de código siguiente se muestra la eliminación incorrecta del objeto SPSite.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_230.

Procedimiento no recomendado de codificación nº 1

Uso del operador de índice

void SPSiteCollectionIndexerLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://moss"))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        SPSite siteCollectionInner = siteCollections[0];
        // SPSite siteCollectionInner leak. 
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}
Private Sub SPSiteCollectionIndexerLeak()
    Using siteCollectionOuter As New SPSite("http://moss")
        Dim webApp As SPWebApplication = siteCollectionOuter.WebApplication
        Dim siteCollections As SPSiteCollection = webApp.Sites

        Dim siteCollectionInner As SPSite = siteCollections(0)
        ' SPSite siteCollectionInner leak. 
    End Using ' SPSite object siteCollectionOuter.Dispose() automatically called.
End Sub

Procedimiento no recomendado de codificación nº 2

Uso del bucle foreach

void SPSiteCollectionForEachLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://moss"))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        foreach (SPSite siteCollectionInner in siteCollections)
        {
            // SPSite siteCollectionInner leak.
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}
Private Sub SPSiteCollectionForEachLeak()
    Using siteCollectionOuter As New SPSite("http://moss")
        Dim webApp As SPWebApplication = siteCollectionOuter.WebApplication
        Dim siteCollections As SPSiteCollection = webApp.Sites

        For Each siteCollectionInner As SPSite In siteCollections
            ' SPSite siteCollectionInner leak.
        Next siteCollectionInner
    End Using ' SPSite object siteCollectionOuter.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación nº 1

Uso del operador de índice

void SPSiteCollectionIndexerNoLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://moss"))
    {
        SPSite siteCollectionInner = null;
        try
        {
            SPWebApplication webApp = siteCollectionOuter.WebApplication;
            SPSiteCollection siteCollections = webApp.Sites;

            siteCollectionInner = siteCollections[0];
        }
        finally
        {
            if (siteCollectionInner != null)
                siteCollectionInner.Dispose();
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}
Private Sub SPSiteCollectionIndexerNoLeak()
    Using siteCollectionOuter As New SPSite("http://moss")
        Dim siteCollectionInner As SPSite = Nothing
        Try
            Dim webApp As SPWebApplication = siteCollectionOuter.WebApplication
            Dim siteCollections As SPSiteCollection = webApp.Sites

            siteCollectionInner = siteCollections(0)
        Finally
            If siteCollectionInner IsNot Nothing Then
                siteCollectionInner.Dispose()
            End If
        End Try
    End Using ' SPSite object siteCollectionOuter.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación nº 2

Uso del bucle foreach

void SPSiteCollectionForEachNoLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://yoursite”))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        foreach (SPSite siteCollectionInner in siteCollections)
        {
            try
            {
                // ...
            }
            finally
            {
                if(siteCollectionInner != null)
                    siteCollectionInner.Dispose();
            }
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}
Private Sub SPSiteCollectionForEachNoLeak()

    Using siteCollectionOuter As SPSite = New SPSite("http://yoursite")
        Dim webApp As SPWebApplication = siteCollectionOuter.WebApplication
        Dim siteCollections As SPSiteCollection = webApp.Sites
        For Each siteCollectionInner As SPSite In siteCollections
            Try
                ' ...
            Finally
                If siteCollectionInner IsNot Nothing Then
                    siteCollectionInner.Dispose()
                End If
            End Try
        Next
    End Using
End Sub

Propiedad SPSite.AllWebs (SPWebCollection)

En esta sección se describen los métodos, propiedades u operadores de la colección de propiedades AllWebs que requieren que se cierre el objeto SPWeb después de obtener acceso.

Método SPSite.AllWebs.Add

El método SPSite.AllWebs.Add crea y devuelve un objeto SPWeb. Debería eliminar los objetos SPWeb devueltos desde SPSite.AllWebs.Add.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_150.

Procedimiento no recomendado de codificación

void AllWebsAddLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb web = siteCollection.AllWebs.Add("site-relative URL");
        // SPWeb object leaked.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub AllWebsAddLeak()
    Using siteCollection As New SPSite("http://moss")
        Dim web As SPWeb = siteCollection.AllWebs.Add("site-relative URL")
        ' SPWeb object leaked.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void AllWebsAddNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub AllWebsAddNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.AllWebs.Add("site-relative URL")
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Método SPWebCollection.Add

El método SPWebCollection.Add crea y devuelve un objeto SPWeb que se debe eliminar.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_200.

Procedimiento no recomendado de codificación

void SPWebCollectionAddLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
            SPWeb innerWeb = webCollection.Add(strWebUrl);  // Must dispose innerWeb.
            // innerWeb leak.
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub SPWebCollectionAddLeak(ByVal strWebUrl As String)
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            Dim webCollection As SPWebCollection = siteCollection.AllWebs ' No AllWebs leak just getting reference.
            Dim innerWeb As SPWeb = webCollection.Add(strWebUrl) ' Must dispose innerWeb.
            ' innerWeb leak.
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void SPWebCollectionAddNoLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
            using (SPWeb innerWeb = webCollection.Add(strWebUrl))
            {
                //...
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub SPWebCollectionAddNoLeak(ByVal strWebUrl As String)
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            Dim webCollection As SPWebCollection = siteCollection.AllWebs ' No AllWebs leak just getting reference.
            Using innerWeb As SPWeb = webCollection.Add(strWebUrl)
                '...
            End Using
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Operador de índice SPSite.AllWebs [ ]

El operador de índice SPSite.AllWebs [] devuelve una nueva instancia de SPWeb cada vez que se obtiene acceso a él. Incluso si ya se ha obtenido acceso a ese objeto, se crea un objeto durante la operación de indización. Si no se cerró correctamente, los siguientes ejemplos de código dejan un objeto SPWeb en el recolector de elementos no utilizados de .NET Framework.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_130.

Procedimiento no recomendado de codificación

void AllWebsForEachLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                // Explicitly dispose here to avoid out of memory leaks with large number of SPWeb objects.
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub AllWebsForEachLeak()
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            For Each innerWeb As SPWeb In siteCollection.AllWebs
                ' Explicitly dispose here to avoid out of memory leaks with large number of SPWeb objects.
            Next
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación nº 1

Uso del bucle foreach

void AllWebsForEachNoLeakOrMemoryOOM()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                try
                {
                    // ...
                }
                finally
                {
                    if(innerWeb != null)
                        innerWeb.Dispose();
                }
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub AllWebsForEachNoLeakOrMemoryOOM()
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            For Each innerWeb As SPWeb In siteCollection.AllWebs
                Try
                    ' ...
                Finally
                    If innerWeb IsNot Nothing Then
                        innerWeb.Dispose()
                    End If
                End Try
            Next
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación nº 2

Uso del operador de índice

void AllWebsIndexerNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.AllWebs[0])
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub AllWebsIndexerNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.AllWebs(0)
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Métodos SPSite.OpenWeb y SPSite. SelfServiceCreateSite

Los métodos OpenWeb() y SelfServiceCreateSite (todas las firmas) del objeto SPSite crean un objeto SPWeb y lo devuelven al llamador. Este nuevo objeto no se almacena en el objeto SPSite y no se elimina en ningún lugar de la clase SPSite. Por este motivo, debe eliminar los objetos creados a través de estos métodos.

Procedimiento no recomendado de codificación

void OpenWebLeak()
{
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
        // SPSite leaked !
    } // SPWeb object web.Dispose() automatically called.
}
Private Sub OpenWebLeak()
    Using web As SPWeb = New SPSite(SPContext.Current.Web.Url).OpenWeb()
        ' SPSite leaked !
    End Using ' SPWeb object web.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void OpenWebNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub OpenWebNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Propiedad SPSite.RootWeb

En instrucciones anteriores se indicaba que la aplicación de llamada debía eliminar la propiedad SPSite.RootWeb justo antes de eliminar el objeto SPSite que la estaba usando. Éstas ya no son las instrucciones oficiales. La limpieza de eliminación se controla automáticamente mediante SharePoint Foundation y SharePoint Server. Además, las propiedades LockIssue, Owner y SecondaryContact de SPSite usaban la propiedad RootWeb internamente. Debido a las instrucciones actualizadas para RootWeb, ya no se recomienda llamar al método Dispose en la propiedad SPSite.RootWeb cuando se usa una de estas propiedades.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_140.

Procedimiento recomendado de codificación

public void RootWebBestPractice()
{
    // New SPSite.
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb rootWeb1 = siteCollection.RootWeb;
        // No explicit rootWeb1 dispose required.
    }  // siteCollection automatically disposed by implementing using().
    // rootWeb1 will be Disposed by SPSite.

    // SPContext and SPControl
    SPWeb rootWeb2 = SPContext.Current.Site.RootWeb;
    // Also would apply to SPControl.GetContextSite(Context);
    // No explicit rootWeb2 dispose required because it is obtained from SPContext.Current.Site.
}
Public Sub RootWebBestPractice()
    ' New SPSite.
    Using siteCollection As New SPSite("http://moss")
        Dim rootWeb1 As SPWeb = siteCollection.RootWeb
        ' No explicit rootWeb1 dispose required.
    End Using ' siteCollection automatically disposed by implementing using().
    ' rootWeb1 will be Disposed by SPSite.

    ' SPContext and SPControl
    Dim rootWeb2 As SPWeb = SPContext.Current.Site.RootWeb
    ' Also would apply to SPControl.GetContextSite(Context);
    ' No explicit rootWeb2 dispose required because it is obtained from SPContext.Current.Site.
End Sub

Microsoft.Office.Server.UserProfiles.PersonalSite (solo Office SharePoint Server 2007)

Microsoft.Office.Server.UserProfiles.PersonalSite devuelve un objeto SPSite que se debe eliminar.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_400.

Procedimiento no recomendado de codificación

void PersonalSiteLeak()
{
    // Open a site collection.
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
        UserProfile profile = profileManager.GetUserProfile("domain\\username");
        SPSite personalSite = profile.PersonalSite;    // Will leak.
    }
}
Private Sub PersonalSiteLeak()
    ' Open a site collection.
    Using siteCollection As New SPSite("http://moss")
        Dim profileManager As New UserProfileManager(ServerContext.GetContext(siteCollection))
        Dim profile As UserProfile = profileManager.GetUserProfile("domain\username")
        Dim personalSite As SPSite = profile.PersonalSite ' Will leak.
    End Using
End Sub

Procedimiento recomendado de codificación

void PersonalSiteNoLeak()
{
    // Open a site collection.
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
        UserProfile profile = profileManager.GetUserProfile("domain\\username");
        using (SPSite personalSite = profile.PersonalSite)
        {
            // ...
        }
    }
}
Private Sub PersonalSiteNoLeak()
    ' Open a site collection.
    Using siteCollection As New SPSite("http://moss")
        Dim profileManager As New UserProfileManager(ServerContext.GetContext(siteCollection))
        Dim profile As UserProfile = profileManager.GetUserProfile("domain\username")
        Using personalSite As SPSite = profile.PersonalSite
            ' ...
        End Using
    End Using
End Sub

En otro caso límite, UserProfiles.PersonalSite tiene pérdidas, como se muestra en el ejemplo de código siguiente.

void PersonalSiteLeak()
{
    // Open a site collection.
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
        UserProfile profile = profileManager.GetUserProfile("domain\\username");
        SPSite personalSite = profile.PersonalSite;    // Will leak.
    }
}
Private Sub PersonalSiteLeak()
    ' Open a site collection.
    Using siteCollection As New SPSite("http://moss")
        Dim profileManager As New UserProfileManager(ServerContext.GetContext(siteCollection))
        Dim profile As UserProfile = profileManager.GetUserProfile("domain\username")
        Dim personalSite As SPSite = profile.PersonalSite ' Will leak.
    End Using
End Sub

Para resolver este tipo de pérdidas, siga el modelo que se muestra en el siguiente ejemplo de código.

void PersonalSiteNoLeak()
{
    // Open a site collection
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
        UserProfile profile = profileManager.GetUserProfile("domain\\username");
        using (SPSite personalSite = profile.PersonalSite)
        {
            // ...
        }
    }
}
Private Sub PersonalSiteNoLeak()
    ' Open a site collection
    Using siteCollection As New SPSite("http://moss")
        Dim profileManager As New UserProfileManager(ServerContext.GetContext(siteCollection))
        Dim profile As UserProfile = profileManager.GetUserProfile("domain\username")
        Using personalSite As SPSite = profile.PersonalSite
            ' ...
        End Using
    End Using
End Sub

Observe también que puede mejorar el rendimiento (y evitar la creación de un objeto SPSite) si recupera un objeto PersonalSite de ProfileLoader, como se muestra en el ejemplo de código siguiente.

UserProfile myProfile = ProfileLoader.GetProfileLoader().GetUserProfile();
using (SPSite personalSite = myProfile.PersonalSite)
{
     // ...
}
Dim myProfile As UserProfile = ProfileLoader.GetProfileLoader().GetUserProfile()
Using personalSite As SPSite = myProfile.PersonalSite
       ' ...
End Using

Además, si va a crear un elemento web para un Mi sitio, puede usar una instancia de PersonalSite que no necesita ser eliminada.

IPersonalPage currentMySitePage = this.Page as IPersonalPage;
if (currentMySitePage != null && !currentMySitePage.IsProfileError)
{
     SPSite personalSite = currentMySitePage.PersonalSite; // Will not leak.
     // ...
}
Dim currentMySitePage As IPersonalPage = TryCast(Me.Page, IPersonalPage)
If currentMySitePage IsNot Nothing AndAlso (Not currentMySitePage.IsProfileError) Then
         Dim personalSite As SPSite = currentMySitePage.PersonalSite ' Will not leak.
         ' ...
End If

Objetos SPWeb

En esta sección se describen las situaciones en las que se devuelven objetos SPWeb y es posible que se deban eliminar.

Propiedad SPWeb.ParentWeb

Instrucciones actualizadas

En instrucciones anteriores se recomendaba que la aplicación de llamada eliminara SPWeb.ParentWeb. Éstas ya no son las instrucciones oficiales. La limpieza de eliminación se controla automáticamente mediante SharePoint Foundation y SharePoint Server.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_170.

Procedimiento recomendado de codificación

using (SPSite site = new SPSite("https://localhost")) 
{
    using (SPWeb web = site.OpenWeb())
    {
        SPList list = web.Lists["Announcements"];
        SPWeb parentWeb = list.ParentWeb; //No explicit dispose required.
    }
}
Using site As New SPSite("https://localhost")
      Using web As SPWeb = site.OpenWeb()
            Dim list As SPList = web.Lists("Announcements")
            Dim parentWeb As SPWeb = list.ParentWeb 'No explicit dispose required.
      End Using
End Using

Propiedad SPWeb.Webs

En esta sección se describen los métodos, propiedades u operadores de la colección de propiedades Webs que requieren que se elimine el objeto SPWeb después de obtener acceso.

SPWeb.Webs

La propiedad SPWeb.Webs devuelve un objeto SPWebCollection. Los objetos SPWeb de esta colección deben eliminarse.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_180.

Procedimiento no recomendado de codificación

void WebsLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                // SPWeb innerWeb leak.
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub WebsLeak()
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            For Each innerWeb As SPWeb In outerWeb.Webs
                ' SPWeb innerWeb leak.
            Next
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void WebsNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                try // Should be first statement after foreach.
                {
                    // ...
                }
                finally
                {
                    if(innerWeb != null)
                        innerWeb.Dispose();
                }
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub WebsNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using outerWeb As SPWeb = siteCollection.OpenWeb()
            For Each innerWeb As SPWeb In outerWeb.Webs
                Try ' Should be first statement after foreach.
                    ' ...
                Finally
                    If innerWeb IsNot Nothing Then
                        innerWeb.Dispose()
                    End If
                End Try
            Next
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

SPWeb.Webs.Add

El método SPWeb.Webs.Add (o SPWebCollection.Add) crea y devuelve un nuevo objeto SPWeb. Debería eliminar los objetos SPWeb que devuelve esta llamada al método.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_190.

Procedimiento no recomendado de codificación

void WebsAddLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPWeb addedWeb = web.Webs.Add(strWebUrl);   // Will leak.

        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub WebsAddLeak(ByVal strWebUrl As String)
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Dim addedWeb As SPWeb = web.Webs.Add(strWebUrl) ' Will leak.

        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void WebsAddNoLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            using (SPWeb addedWeb = web.Webs.Add(strWebUrl))
            {
                //..
            }

        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub WebsAddNoLeak(ByVal strWebUrl As String)
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Using addedWeb As SPWeb = web.Webs.Add(strWebUrl)
                '..
            End Using

        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Operador de índice SPWeb.Webs[]

El operador de índice SPWeb.Webs[] devuelve un nuevo objeto SPWeb para cada acceso. Incluso si ya se ha obtenido acceso a ese objeto, se crea un SPWeb mediante la llamada al método OpenWeb. Los siguientes ejemplos de código ocasionan la retención a largo plazo de estos objetos en memoria que usa .NET Framework.

Procedimiento no recomendado de codificación nº 1

Uso del bucle For

int i;

SPWeb oSPWeb, oSPWeb2;
SPSite oSPSite = SPControl.GetContextSite(Context);

oSPWeb = oSPSite.OpenWeb();

for(i = 0;i < oSPWeb.Webs.Count;i++)
{
   oSPWeb2 = oSPWeb.Webs[i];
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title);
}
Dim i As Integer

Dim oSPWeb, oSPWeb2 As SPWeb
Dim oSPSite As SPSite = SPControl.GetContextSite(Context)

oSPWeb = oSPSite.OpenWeb()

For i = 0 To oSPWeb.Webs.Count - 1
   oSPWeb2 = oSPWeb.Webs(i)
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title)
Next i

Procedimiento no recomendado de codificación nº 2

Uso del bucle foreach

SPWeb oSPWeb, oSPWeb2;
SPSite oSPSite = SPControl.GetContextSite(Context);

oSPWeb = oSPSite.OpenWeb();

foreach(SPWeb oSPWeb2 in oSPWebe.Webs)
{
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title);
}
Dim oSPWeb, oSPWeb2 As SPWeb
Dim oSPSite As SPSite = SPControl.GetContextSite(Context)

oSPWeb = oSPSite.OpenWeb()

For Each oSPWeb2 As SPWeb In oSPWebe.Webs
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title)
Next

La corrección recomendada consiste en eliminar al final de cada bucle.

Procedimiento recomendado de codificación nº 1

Uso del bucle For

int i;

SPWeb oSPWeb, oSPWeb2;
SPSite oSPSite = SPControl.GetContextSite(Context);

oSPWeb = oSPSite.OpenWeb();

for(i = 0;i < oSPWeb.Webs.Count;i++)
{
   oSPWeb2 = oSPWeb.Webs[i];
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title);
   oSPWeb2.Dispose();
}

oSPWeb.Dispose();
Dim i As Integer

Dim oSPWeb, oSPWeb2 As SPWeb
Dim oSPSite As SPSite = SPControl.GetContextSite(Context)

oSPWeb = oSPSite.OpenWeb()

For i = 0 To oSPWeb.Webs.Count - 1
   oSPWeb2 = oSPWeb.Webs(i)
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title)
   oSPWeb2.Dispose()
Next i

oSPWeb.Dispose()

Procedimiento recomendado de codificación nº 2

Uso del bucle foreach

SPWeb oSPWeb, oSPWeb2;
SPSite oSPSite = SPControl.GetContextSite(Context);

oSPWeb = oSPSite.OpenWeb();

foreach(SPWeb oSPWeb2 in oSPWeb.Webs)
{
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title);
   oSPWeb2.Dispose();
}

oSPWeb.Dispose();
Dim oSPWeb, oSPWeb2 As SPWeb
Dim oSPSite As SPSite = SPControl.GetContextSite(Context)

oSPWeb = oSPSite.OpenWeb()

For Each oSPWeb2 As SPWeb In oSPWeb.Webs
   BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title)
   oSPWeb2.Dispose()
Next

oSPWeb.Dispose()

Procedimiento recomendado de codificación nº 3

Uso del bucle for con eliminación automática

int i;

SPWeb oSPWeb, oSPWeb2;
SPSite oSPSite = SPControl.GetContextSite(Context);

using(oSPWeb = oSPSite.OpenWeb())
{
   for(i = 0;i < oSPWeb.Webs.Count;i++)
   {
      Using(oSPWeb2 = oSPWeb.Webs[i])
      {
         BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title);
      }
   }
}
Dim i As Integer
Dim oSPSite As SPSite = SPControl.GetContextSite(Context)

Using oSPWeb As SPWeb = oSPSite.OpenWeb()
    For i = 0 To oSPWeb.Webs.Count - 1
        Using oSPWeb2 As SPWeb = oSPWeb.Webs(i)
                BuildTableRow(oDisplayTable, "Web", oSPWeb2.Title)
        End Using
    Next
End Using

Otros objetos que requieren eliminación

En esta sección se indica cuándo se debe llamar al método Dispose en otros objetos de SharePoint.

Propiedad Microsoft.SharePoint.Portal.SiteData.Area.Web

La propiedad Web de la clase SharePoint.Portal.SiteData.Area devuelve un nuevo objeto SPWeb cada vez que se tiene acceso a ella. Cada uso de la propiedad Area.Web debería tener una correspondiente llamada al método Dispose. Aunque las clases Area y AreaManager ahora son obsoletas, esto sigue siendo una preocupación al migrar código heredado.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_500.

Procedimiento no recomendado de codificación

void AreaWebLeak()
{
    // AreaManager and Area are obsolete in SharePoint Server, but this
    // should still be noted.
    Area area = AreaManager.GetArea(PortalContext.Current, new Guid("{GUID}"));
    string str = area.Web.Title;
    // SPWeb area.Web leak.
}
Private Sub AreaWebLeak()
    ' AreaManager and Area are obsolete in SharePoint Server, but this
    ' should still be noted.
    Dim area As Area = AreaManager.GetArea(PortalContext.Current, New Guid("{GUID}"))
    Dim str As String = area.Web.Title
    ' SPWeb area.Web leak.
End Sub

Procedimiento recomendado de codificación

public void AreaWebNoLeak()
{
    // AreaManager and Area are obsolete but this should still be noted.
    Area area = AreaManager.GetArea(PortalContext.Current, new Guid("{GUID}"));
    using (SPWeb areaWeb = area.Web)
    {
        string str = areaWeb.Title;
    }
}
Public Sub AreaWebNoLeak()
    ' AreaManager and Area are obsolete but this should still be noted.
    Dim area As Area = AreaManager.GetArea(PortalContext.Current, New Guid("{GUID}"))
    Using areaWeb As SPWeb = area.Web
        Dim str As String = areaWeb.Title
    End Using
End Sub

Métodos SPControl.GetContextSite y SPControl.GetContextWeb

Si el objeto se obtiene de los objetos de contexto de SharePoint (los métodos GetContextSite y GetContextWeb de la clase SPControl), la aplicación de llamada no debe llamar al método Dispose en el objeto. Si lo hace, puede ocasionar que el modelo de objetos de SharePoint se comporte de forma inesperada o se produzca un error. Esto se debe a una lista interna que se mantiene en los objetos SPSite y SPWeb derivados de este modo. Internamente, el modelo de objetos enumera esta lista una vez que se haya completado la página para eliminar los objetos correctamente.

Aún debería eliminar un objeto que se crea a partir de estos objetos, por ejemplo, si se abre un sitio web desde un objeto SPSite que obtuvo mediante el método GetContextSite.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_210.

Procedimiento no recomendado de codificación

void SPControlBADPractice()
{
    SPSite siteCollection = SPControl.GetContextSite(Context);
    siteCollection.Dispose();   // DO NOT DO THIS.
    SPWeb web = SPControl.GetContextWeb(Context);
    web.Dispose();  // DO NOT DO THIS.
}
Private Sub SPControlBADPractice()
    Dim siteCollection As SPSite = SPControl.GetContextSite(Context)
    siteCollection.Dispose() ' DO NOT DO THIS.
    Dim web As SPWeb = SPControl.GetContextWeb(Context)
    web.Dispose() ' DO NOT DO THIS.
End Sub

Procedimiento recomendado de codificación

void SPControlBestPractice()
{
    SPSite siteCollection = SPControl.GetContextSite(Context);
    SPWeb web = SPControl.GetContextWeb(Context);
    // Do NOT call Dispose().
}
Private Sub SPControlBestPractice()
      Dim siteCollection As SPSite = SPControl.GetContextSite(Context)
      Dim web As SPWeb = SPControl.GetContextWeb(Context)
      ' Do NOT call Dispose().
End Sub

Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager

La clase SPLimitedWebPartManager contiene una referencia a un objeto interno SPWeb que debe eliminarse.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_160.

Procedimiento no recomendado de codificación

void SPLimitedWebPartManagerLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
            SPLimitedWebPartManager webPartManager =
                page.GetLimitedWebPartManager(PersonalizationScope.Shared);
            // SPWeb object webPartManager.Web leaked.
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub SPLimitedWebPartManagerLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Dim page As SPFile = web.GetFile("Source_Folder_Name/Source_Page")
            Dim webPartManager As SPLimitedWebPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared)
            ' SPWeb object webPartManager.Web leaked.
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void SPLimitedWebPartManagerLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
            SPLimitedWebPartManager webPartManager =
                page.GetLimitedWebPartManager(PersonalizationScope.Shared);
                webPartManaber.Web.Dispose();
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub SPLimitedWebPartManagerLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Dim page As SPFile = web.GetFile("Source_Folder_Name/Source_Page")
            Dim webPartManager As SPLimitedWebPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared)
            webPartManaber.Web.Dispose()
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Microsoft.SharePoint.Publishing.PublishingWeb

Nota

El espacio de nombres Microsoft.SharePoint.Publishing pertenece a SharePoint Server 2010. Esta sección se aplica a SharePoint Server 2010 y no a SharePoint Foundation 2010.

El método GetPublishingWebs de la clase PublishingWeb devuelve un objeto PublishingWebCollection. Debe llamar al método Close en cada objeto enumerado innerPubWeb. Cuando llama solo al método GetPublishingWeb, no es necesario que llame a Close.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_300.

Procedimiento no recomendado de codificación

void PublishingWebCollectionLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            // Passing in SPWeb object that you own, no dispose needed on
            // outerPubWeb.
            PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);

            PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
            foreach (PublishingWeb innerPubWeb in pubWebCollection)
            {
                // innerPubWeb leak.
            }
            // PublishingWeb will leak for each innerPubWeb referenced
        } // SPWeb object web.Dispose() automatically called.
    } // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub PublishingWebCollectionLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            ' Passing in SPWeb object that you own, no dispose needed on
            ' outerPubWeb.
            Dim outerPubWeb As PublishingWeb = PublishingWeb.GetPublishingWeb(web)

            Dim pubWebCollection As PublishingWebCollection = outerPubWeb.GetPublishingWebs()
            For Each innerPubWeb As PublishingWeb In pubWebCollection
                ' innerPubWeb leak.
            Next
            ' PublishingWeb will leak for each innerPubWeb referenced
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void PublishingWebCollectionNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            // Passing in SPWeb object that you own, no dispose needed on
            // outerPubWeb.
            PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);
            PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
            foreach (PublishingWeb innerPubWeb in pubWebCollection)
            {
                try
                {
                    // ...
                }
                finally
                {
                    if(innerPubWeb != null)
                        innerPubWeb.Close();
                }
            }
        }  // SPWeb object web.Dispose() automatically called.
    } // SPSite object siteCollection.Dispose() automatically called.
}
Private Sub PublishingWebCollectionNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            ' Passing in SPWeb object that you own, no dispose needed on
            ' outerPubWeb.
            Dim outerPubWeb As PublishingWeb = PublishingWeb.GetPublishingWeb(web)
            Dim pubWebCollection As PublishingWebCollection = outerPubWeb.GetPublishingWebs()
            For Each innerPubWeb As PublishingWeb In pubWebCollection
                Try
                    ' ...
                Finally
                    If innerPubWeb IsNot Nothing Then
                        innerPubWeb.Close()
                    End If
                End Try
            Next
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Nota

Existe un requisito similar para llamar a Close en cada objeto PublishingWeb creado mediante la llamada al método Add en el PublishingWebCollection devuelto mediante Microsoft.SharePoint.Publishing.PublishingWeb.GetPublishingWebs. Para obtener un ejemplo de código, vea el método GetPublishingWebs(). Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_310.

El método Microsoft.SharePoint.Publishing.PublishingWeb.GetVariation devuelve un objeto PublishingWeb que se debe eliminar.

Nota

Este procedimiento recomendado resuelve el problema que la herramienta SharePoint Dispose Checker Tool identifica como SPDisposeCheckID_320.

Procedimiento no recomendado de codificación

void GetVariationLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);  // Passing in SPWeb object, so no Close() needed
            VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];
            PublishingWeb variationPublishingWeb = publishingWeb.GetVariation(variationLabel);  // Must be Closed().
            // ...
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub GetVariationLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Dim publishingWeb As PublishingWeb = PublishingWeb.GetPublishingWeb(web) ' Passing in SPWeb object, so no Close() needed
            Dim variationLabel As VariationLabel = Variations.Current.UserAccessibleLabels(0)
            Dim variationPublishingWeb As PublishingWeb = publishingWeb.GetVariation(variationLabel) ' Must be Closed().
            ' ...
        End Using ' SPWeb object outerWeb.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Procedimiento recomendado de codificación

void GetVariationNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            PublishingWeb variationPublishingWeb = null;
            try
            {
                PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);  // Passing in SPWeb object, so no Close() needed.
                VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];
                variationPublishingWeb = publishingWeb.GetVariation(variationLabel);  // Must be Closed().
                // ...
            }
            finally
            {
                if(variationPublishingWeb != null)
                    variationPublishingWeb.Close();
            }
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}
Private Sub GetVariationNoLeak()
    Using siteCollection As New SPSite("http://moss")
        Using web As SPWeb = siteCollection.OpenWeb()
            Dim variationPublishingWeb As PublishingWeb = Nothing
            Try
                Dim publishingWeb As PublishingWeb = PublishingWeb.GetPublishingWeb(web) ' Passing in SPWeb object, so no Close() needed.
                Dim variationLabel As VariationLabel = Variations.Current.UserAccessibleLabels(0)
                variationPublishingWeb = publishingWeb.GetVariation(variationLabel) ' Must be Closed().
                ' ...
            Finally
                If variationPublishingWeb IsNot Nothing Then
                    variationPublishingWeb.Close()
                End If
            End Try
        End Using ' SPWeb object web.Dispose() automatically called.
    End Using ' SPSite object siteCollection.Dispose() automatically called.
End Sub

Modelos de eliminación entre métodos

En el ejemplo siguiente se muestra la práctica común de retención de los objetos SPSite y SPWeb entre métodos de una clase. A veces este modelo de diseño es necesario, pero asegúrese de no olvidar el momento adecuado para llamar a Dispose cuando termine de realizar las llamadas entre métodos. En el ejemplo de código siguiente se muestra un modelo en el que SPSite y SPWeb tienen pérdidas cuando la clase se sale del ámbito.

public class CrossMethodLeak
{
    private SPSite _siteCollection = null;
    private SPWeb _web = null;

    public void MethodA()
    {
        _siteCollection = new SPSite("http://moss");
        _web = _siteCollection.OpenWeb();
    }

    public void MethodB()
    {
        if (_web != null)
        {
            string title = _web.Title;
        }
    }

    public void MethodC()
    {
        if (_web != null)
        {
            string name = _web.Name;
        }
    }
}
Public Class CrossMethodLeak
    Private _siteCollection As SPSite = Nothing
    Private _web As SPWeb = Nothing

    Public Sub MethodA()
        _siteCollection = New SPSite("http://moss")
        _web = _siteCollection.OpenWeb()
    End Sub

    Public Sub MethodB()
        If _web IsNot Nothing Then
            Dim title As String = _web.Title
        End If
    End Sub

    Public Sub MethodC()
        If _web IsNot Nothing Then
            Dim name As String = _web.Name
        End If
    End Sub
End Class

Conclusión

Debido a que muchos objetos de SharePoint implementan la interfaz IDisposable, debe tener cuidado al usar estos objetos para evitar su retención en la memoria. Si sigue las instrucciones de eliminación de objetos de SharePoint, como se describe en este artículo, puede ayudar a garantizar la confiabilidad del código personalizado.

Agradecimientos

Nos gustaría agradecer a las siguientes personas por sus aportes y orientación en la creación de este artículo:

  • Steve Sheppard, Microsoft Corporation

  • Chris Gideon, Microsoft Corporation

  • Rashid Aga, Microsoft Corporation

Vea también

Otros recursos

SharePoint Dispose Checker Tool

Guía de SharePoint de Patterns & Practices

Centro para desarrolladores de Windows SharePoint Services

Centro para desarrolladores de SharePoint Server 2007

Prácticas recomendadas de personalización de Productos y Tecnologías de SharePoint

Centro de recursos de procedimientos recomendados para SharePoint Server 2007

Blog de Roger Lamb para programadores de SharePoint

Prácticas recomendadas: Problemas de codificación habituales al usar el modelo de objetos de SharePoint