为什么我的ASP.Net静态函数的"上下文"在用户会话之间交叉?

Mat*_*ith 7 asp.net static-methods

我想我需要一些帮助来理解静态对象如何在ASP.Net应用程序中持续存在.我有这种情况:

类库中的someFile.cs:

public delegate void CustomFunction();

public static class A {
    public static CustomFunction Func = null;
}
Run Code Online (Sandbox Code Playgroud)

类库中的someOtherFile.cs:

public class Q {
    public Q() {
        if (A.Func != null) {
            A.Func();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一些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();
}
Run Code Online (Sandbox Code Playgroud)

我的想法是,我有一个业务对象,它根据UI级别的回调函数执行一些操作.我将回调函数设置为Page_Init上的静态变量(在实际代码版本中,在主页面中,如果这有所不同).我认为页面的每次执行,无论它来自哪个用户会话,都会通过该函数的逻辑,但是在自己的数据集上运行.似乎正在发生的是并发问题.

如果我运行一个用户会话,那么当它在对该回调函数的调用之间休眠时,启动另一个用户会话,当第一个会话从休眠状态返回时,它从第二个用户会话中获取会话ID.这怎么可能?

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)
Run Code Online (Sandbox Code Playgroud)

为什么函数的上下文(意思,本地数据等)从一个用户会话被覆盖到另一个用户会话?

Joe*_*orn 11

每个对asp.net站点的请求都会进入并在其自己的线程上处理.但是每个线程都属于同一个应用程序.这意味着您标记为静态的任何内容都将在所有请求之间共享,因此也是所有会话和用户共享.

在这种情况下,MyFunc这是你的网页类的部分功能是复制了静态的顶部Func成员在A每page_init等每任何用户执行page_init时间,他更换A.Func使用的所有请求.

  • 它通过闭合来实现. (2认同)

Kei*_*ler 2

您可能考虑的一种解决方案是使用 [ThreadStatic]。

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

它将使你的每个线程的静态数据。然而,有一些警告,所以你应该测试一下。

  • ThreadStatic 变量的替代方案是 HttpContext.Current.Items,它的范围仅限于不同的请求(例如,请参阅 http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx)。 (2认同)