Solucionar problemas de aplicaciones de ASP.NET con el uso de palabras clave static

Seleccione idioma Seleccione idioma
Id. de artículo: 893666 - Ver los productos a los que se aplica este artículo
Columna de voz de soporte ASP.NET

Solucionar problemas de aplicaciones de ASP.NET con el uso de palabras clave static

para personalizar esta columna a sus necesidades, deseamos invitar a enviar sus ideas sobre temas que le interesen y resuelve los problemas que se desea ver artículos de Knowledge Base en el futuro y columnas de voz de soporte. Puede enviar sus ideas y comentarios mediante el formulario Ask For It. También es un vínculo al formulario en la parte inferior de esta columna.
Expandir todo | Contraer todo

En esta página

Bienvenido a la columna de voz de soporte técnico de Microsoft ASP.NET Mi nombre es Jerry Couto. Han con Microsoft 5 años y ha dedicado la mayor parte mi tiempo centrada en tecnologías relacionadas con Web como Microsoft FrontPage y las nuevas tecnologías Microsoft SharePoint. He dedicado el último año trabajar con Microsoft ASP.NET como ingeniero de soporte técnico. Este mes en la columna de voz de soporte, voy a describir la solución de problemas de aplicaciones ASP.NET con el uso de palabras clave static.

Variables estáticas

Este artículo describen dos comportamientos diferentes que están causados por palabras clave static y que puede ser difícil solucionar. Espero que después de leer este artículo, puede evitar estos comportamientos en sus aplicaciones y poder mejor diagnosticar si se producen.

Los usuarios ver datos incorrectos

Un síntoma que es muy difícil solucionar problemas se produce cuando un usuario envía datos, pero se muestra información de otro usuario o se escribe en una base de datos. Esto normalmente ocurre debido de uso incorrecto de las variables estáticas de clases. Un objeto estático es instancia una vez para cada dominio de aplicación y todo el procesamiento de la aplicación comparte el mismo objeto. Por ejemplo, supongamos que configurar una propiedad estática en una clase mediante el código siguiente.
using System;

namespace statics
{
	public class BadClass
	{
		private static string _MyData;

		public static string MyData
		{
			get{return _MyData;}
			set{_MyData = value;}
		}
	}
}
La propiedad MyData es estático y público. Puede obtener acceso lo en cualquier lugar de la aplicación mediante la sintaxis siguiente:

BadClass.MyData

Ahora imagine que tiene una página que establece el valor de MyData y, a continuación, algunos funciona con él. Si varios usuarios visita la página al mismo tiempo, tiene ahora una condición de anticipación donde gana el último usuario había actualizado MyData . En el ejemplo siguiente se muestra este comportamiento estableciendo el objeto estático durante un evento button_click . En este ejemplo también se crea la suspensión de subproceso durante 15 segundos. Esto permite que ambas solicitudes a ejecutar al mismo tiempo. Para ello, siga estos pasos:
  1. Crear un formulario Web Forms de aspx.
  2. Agregar una etiqueta, un botón y un cuadro de texto. El código HTML será similar al siguiente.
    <body>
    	<form id="Form1" method="post" runat="server">
    		<asp:Label id="Label1" runat="server"></asp:Label>
    		<br>
    		<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>
    		</br>
    		<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
    	</form>
    </body>
    
    
  3. Haga doble clic en el botón para crear un evento button_click .
    private void Button1_Click(object sender, System.EventArgs e)
    {
    	//Set the static property to the value of the text box.
    	BadClass.MyData = TextBox1.Text;
    
    	//Make the thread wait 30 seconds
    	System.Threading.Thread.Sleep(30000);
    
    	//Set the label to the value of the property.
    	Label1.Text = BadClass.MyData;
    }
  4. Abierto independiente dos procesos de Microsoft Internet Explorer:
    1. Haga clic en Inicio , seleccione Todos los programas y, a continuación, haga clic en Internet Explorer .
    2. Repita el paso un.
    Esto se compruebe que dispone Iexplore.exe independiente dos procesos que se ejecutan al mismo tiempo. Puede comprobar el Administrador de tareas para asegurarse de que. Cuando tiene dos procesos Iexplore.exe ejecutando al mismo tiempo, tiene sesiones únicas para cada solicitud de página. Las solicitudes que tienen el mismo identificador de sesión se procesan en el orden en que vienen en y no se ejecutan al mismo tiempo.
  5. Busque la página .aspx en ambas ventanas del explorador.
  6. Enviar Usuario1 en el cuadro de texto de una ventana del explorador y, a continuación, enviar Usuario2 en el cuadro texto de la ventana del explorador.

    Después de completar las páginas, verá Usuario2 en ambas etiquetas.
Como se mencionó anteriormente, ambas páginas se ejecutan al mismo tiempo. La primera solicitud establece la propiedad estática a User1 y, a continuación, va a suspender. Mientras el subproceso está en pausa, otra solicitud entra y establece el mismo objeto a Usuario2. El subproceso que está procesando la primera solicitud completa y, a continuación, muestra el valor. El valor se establece en User2.

Evitar este comportamiento

La mejor manera de evitar este comportamiento es para hacer que no sea el objeto estático y utilizar una instancia de la clase para establecer y recuperar los valores. La propiedad no está compartida porque se crea una copia del objeto para cada solicitud, y no podrá ver este comportamiento. Para evitar este comportamiento, siga estos pasos:
  1. Quite el modificador static desde el archivo BadClass.cs.
    using System;
    
    namespace statics
    {
    	public class BadClass
    	{
    		private string _MyData;  	//Removed static
    	
    		public string MyData		//Removed static
    		{
    			get{return _MyData;}
    			set{_MyData = value;}
    		}
    	}
    }
    
  2. Cambiar el evento button_click .
    private void Button1_Click(object sender, System.EventArgs e)
    {
    	//Create an instance of BadClass
            BadClass _bad = new BadClass();	
    	
    	//Set the MyData property on this instance
            _bad.MyData = TextBox1.Text;
    
            //Sleep for 30 seconds
    	System.Threading.Thread.Sleep(30000);
    
    	//Set the label to the value of the property
    	Label1.Text = _bad.MyData;
    }
    
Si tiene que utilizar el objeto estático, deberá implementar el bloqueo cuando se utiliza el objeto estático. Esto impide que ambos subprocesos tener acceso al objeto al mismo tiempo. Para ello, siga estos pasos:
  1. Agregar un objeto estático al código subyacente de la página. Este objeto será un recurso compartido que las páginas pueden obtener un bloqueo en.
    static object StaticLocker = new object();
  2. Cambiar el evento button_click a la siguiente.
    private void Button1_Click(object sender, System.EventArgs e)
    {
    	//Lock the object to prevent multiple threads from writing to the static property
    	lock(StaticLocker)
    	{
    		//Set the static property
    		BadClass.MyData = TextBox1.Text;
    
    		//Put the thread to sleep for 30 seconds
    		System.Threading.Thread.Sleep(30000);
    
    		//Set the label to the value of the static property
    		Label1.Text = BadClass.MyData;
    	}
    }
    

NullReferenceException causado por datos estáticos

Otro comportamiento que se produce al utilizar estáticos es una excepción System.NullReferenceException. Por ejemplo, cambiar el código de evento button_click a la siguiente.
private void Button1_Click(object sender, System.EventArgs e)
{
	BadClass.MyData = TextBox1.Text;
	System.Threading.Thread.Sleep(10000);
	Label1.Text = BadClass.MyData.ToString();
	BadClass.MyData = null;
}
si realiza la misma prueba como antes, cuando se llama BadClass.MyData.ToString() por la segunda solicitud, producirá una excepción System.NullReferenceException. La excepción se produce porque la primera solicitud de conjunto de System.NullReferenceException estaba esperando el valor null durante la segunda solicitud. La solución para este comportamiento es el mismo que para una propiedad estática.
Pérdida de memoria debido a eventos estáticos
Si ha configurado un evento estático y, a continuación, suscribirse a ese evento desde una página .aspx, el proceso se ejecutará finalmente fuera de la memoria. Consideremos que agregue el siguiente el BadClass.cs archivo
public delegate void MyEvent();
public static event MyEvent BadEvent;
a continuación, conectar el delegado de evento en el método InitializeComponent de la página .aspx a un método en la página.
private void InitializeComponent()
{    
	//Add this with the other items (for example, this.Load).
	BadClass.BadEvent += new BadClass.MyEvent(this.TestEvent);
}
también agregar el método siguiente a la página. Éste es el método que especificó al enlazar el evento en el método InitializeComponent :
private void TestEvent()
{
	//Do some work here.
}
¿Por qué esto produce una pérdida de memoria
Puesto que el evento es estático y nunca queda fuera de ámbito, está agregando el método a la lista de eventos que se desencadena cuando el evento se produce cada vez que se ejecuta la página. El resultado final es que es raíz de cualquier objeto conectar al evento estático en la memoria, y nunca se recopilarán. En este caso, ese objeto es la clase de página .aspx real.

Este comportamiento se produce en el depurador WinDbg.exe o el depurador Cdb.exe ejecutando el ! gcroot comandos en el objeto que está agregando el evento. Verá un resultado similar al siguiente.
HANDLE(Strong):c3d11d8:Root:0x90b8838(System.Object[])->0x5346f68(statics.BadClass/MyEvent)->
0x10ff928(statics.BadClass/MyEvent)->
0x10faa24(statics.BadClass/MyEvent)->
han realizado muchas solicitudes de objeto en los siguientes eventos.
0x10e6fe0(statics.BadClass/MyEvent)->
0x533baf0(ASP.StaticsTest_aspx)
puede ver que el elemento inferior es la clase de página .aspx y que es raíz para varios delegados MyEvent. Porque es raíz de la página .aspx, no se limpian. El otro efecto de lado es que lo está utilizando la página .aspx también no se puede limpiar porque tienen su raíz en el objeto de página.

Para obtener más información sobre el recolector .NET de Microsoft, visite los sitios Web de MSDN siguientes:
http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx
Para obtener más información acerca de la ! gcroot comando y obtener este resultado, consulte la sección "Contadores de memoria de .NET CLR" el siguiente sitio Web de MSDN:
http://msdn2.microsoft.com/en-us/library/ms972959.aspx

Evitar este comportamiento

Para evitar este comportamiento, puede no utilizar la palabra clave static en el evento o quitar el controlador de eventos de la página cuando haya terminado de utilizarlo. En un ejemplo de ASP.NET, conectar el evento cuando se llama Page_Init . Debe quitarlo cuando se descarga la página agregando un controlador de eventos para el evento Page_Unload .

Agregue el siguiente método InitializeComponents .
this.Unload += new System.EventHandler(this.Page_Unload);

Add the following method to the page to remove the event:
private void Page_Unload(object sender, System.EventArgs e)
{
	BadClass.test -= new BadClass.MyEvent(this.TestEvent);
}
para obtener más información acerca de eventos, visite el siguiente sitio Web de MSDN:
http://msdn2.microsoft.com/en-us/library/aa645739(vs.71).aspx
Como siempre, quieres enviar ideas sobre temas que desea dirigidos en futuras columnas o en Knowledge Base utilizando Ask For It.

Propiedades

Id. de artículo: 893666 - Última revisión: martes, 27 de marzo de 2007 - Versión: 1.4
La información de este artículo se refiere a:
  • Microsoft ASP.NET 1.0
  • Microsoft ASP.NET 1.1
Palabras clave: 
kbmt kbhowto kbasp KB893666 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 893666

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com