¿Por qué mi función estática ASP.Net & # 8220; contexto & # 8221; cruce entre sesiones de usuario?

StackOverflow https://stackoverflow.com/questions/1435068

  •  07-07-2019
  •  | 
  •  

Pregunta

Creo que necesito ayuda para comprender cómo persisten los objetos estáticos en una aplicación ASP.Net. Tengo este escenario:

someFile.cs en una biblioteca de clases:

public delegate void CustomFunction();

public static class A {
    public static CustomFunction Func = null;
}

someOtherFile.cs en una biblioteca de clases:

public class Q {
    public Q() {
        if (A.Func != null) {
            A.Func();
        }
    }
}

Alguna página ASP.Net:

Page_Init {
    A.Func = MyFunc;
}

public void MyFunc() {
    System.IO.File.AppendAllText(
        "mydebug.txt", DateTime.Now.ToString("hh/mm/ss.fff", Session.SessionID));
}

Page_Load {
    Q myQ = new Q();
    System.Threading.Thread.Sleep(20000);
    mQ = new Q();
}

La idea es que tengo un objeto comercial que realiza algunas operaciones basadas en una función de devolución de llamada en el nivel de la interfaz de usuario. Establecí la función de devolución de llamada en una variable estática en Page_Init (en la versión de código real, en la página maestra, si eso hace la diferencia). Pensé que cada ejecución de la página, sin importar de qué sesión de usuario provenía, pasaría por la lógica de esa función pero funcionaría en su propio conjunto de datos. En cambio, lo que parece estar sucediendo es un problema de concurrencia.

Si ejecuto una sesión de usuario, mientras duerme entre llamadas a esa función de devolución de llamada, inicie otra sesión de usuario, cuando la primera sesión vuelve de dormir, recoge la ID de sesión de la segunda sesión de usuario. ¿Cómo puede ser esto posible?

Salida de mydebug.txt:

01/01/01.000 abababababab  (session #1, first call)
01/01/05.000 cdcdcdcdcdcd  (session #2, first call - started 5 seconds after session #1)
01/01/21.000 cdcdcdcdcdcd  (session #1 returns after the wait but has assumed the function context from session #2!!!!!)
01/01/25.000 cdcdcdcdcdcd  (session #2 returns with its own context)

¿Por qué se sobrescribe el contexto de la función (es decir, sus datos locales, etc.) de una sesión de usuario a otra?

¿Fue útil?

Solución

Una solución que podría considerar es usar [ThreadStatic].

http://msdn.microsoft. com / es-us / library / system.threadstaticattribute (VS.71) .aspx

Hará sus estadísticas por hilo. Sin embargo, hay cavaets, por lo que debe probar.

Otros consejos

Cada solicitud a un sitio asp.net entra y se procesa en su propio hilo. Pero cada uno de esos hilos pertenece a la misma aplicación. Eso significa que todo lo que marque como estático se comparte entre todas las solicitudes y, por lo tanto, también todas las sesiones y usuarios.

En este caso, la función MyFunc que forma parte de su clase de página se copia sobre el miembro estático Func en A con cada page_init, por lo que cada vez que un usuario hace un page_init, está reemplazando el A.Func utilizado por todas solicitudes.

Los datos estáticos se comparten entre todo el dominio de aplicación de tu aplicación web. En resumen, se comparte entre todos los subprocesos que atienden solicitudes en su aplicación web, no está vinculado a una sesión / subproceso / usuario de ninguna manera, sino a la aplicación web en su conjunto (a diferencia de, por ejemplo, php, donde cada solicitud vive en su propia barra de entorno aislada Se proporcionan algunos botones, como la variable de sesión).

No intentaré mejorar las explicaciones de las otras respuestas sobre los miembros estáticos, pero quiero señalar otra forma de codificar su problema inmediato.

Como solución, puede crear una versión orientada a la instancia de su clase A , almacenarla en una variable de nivel de página y pasarla a Q constructor en la carga de la página:

public class MyPage: Page {
    private A2 _a2;

    // I've modified A2's constructor here to accept the function
    protected Page_Init() { this._a2 = new A2(MyFunc); }

    protected Page_Load() { 
        Q myQ = new Q(this._a2); 
        // etc..
    }
}

De hecho, si no es necesario presionar para declarar A2 antes, puede crear una instancia cuando cree su instancia de Q en Page_Load .

Editar: para responder la pregunta que planteó en otros comentarios, la razón por la que se comparten las variables es que las solicitudes comparten el mismo delegado, que tiene una sola copia de sus variables. Consulte The Beauty of Closures de Jon Skeet para obtener más detalles.

Si desea que los datos persistan solo para la solicitud actual, use HttpContext.Items : http://msdn.microsoft.com/en- us / library / system.web.httpcontext.items.aspx

Si desea que los datos persistan para la sesión del usuario actual (suponiendo que tenga habilitado el estado de la sesión), use HttpContext.Session : http://msdn.microsoft.com/en- us / library / system.web.httpcontext.session.aspx

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top