27

因此,这是我的一堂课的摘录:

    [ThreadStatic]
    readonly static private AccountManager _instance = new AccountManager();

    private AccountManager()
    {
    }

    static public AccountManager Instance
    {
        get { return _instance; }
    }

如您所见,它是一个单例线程——即该实例被标记为 ThreadStatic 属性。该实例也作为静态构造的一部分进行实例化。

既然如此,当我尝试使用 Instance 属性时,怎么可能在我的 ASP.NET MVC 应用程序中得到 NullReferenceException?

4

5 回答 5

38

引用MSDN ThreadStaticAttribute

不要为标有 ThreadStaticAttribute 的字段指定初始值,因为这样的初始化只发生一次,当类构造函数执行时,因此只影响一个线程。如果不指定初始值,则可以依赖被初始化为默认值的字段(如果它是值类型),或者依赖空引用(在 Visual Basic 中为 Nothing)(如果它是引用类型)。

于 2010-01-11T17:19:40.857 回答
13

这是ThreadStatic属性中令人困惑的部分。即使它为每个线程创建一个值,初始化代码也只在其中一个线程上运行。访问此值的所有其他线程将获得该类型的默认值,而不是初始化代码的结果。

代替值初始化,将其包装在为您进行初始化的属性中。

[ThreadStatic]
readonly static private AccountManager _instance;

private AccountManager()
{
}

static public AccountManager Instance
{
  get 
  { 
    if ( _instance == null ) _instance = new AccountManager();
    return _instance; 
  }
}

因为_instance每个线程的值是唯一的,所以属性中不需要锁定,它可以像任何其他延迟初始化的值一样对待。

于 2010-01-11T17:20:23.103 回答
8

您在[ThreadStatic]这里击中了经典的“101”。

静态初始化程序只会触发一次,即使它被标记为[ThreadStatic],所以其他线程(除了第一个线程)将看到这个未初始化。

于 2010-01-11T17:20:47.237 回答
1

我相信发生的事情是静态字段仅被初始化一次,因此当另一个线程尝试读取该字段时,它将为空(因为它是默认值),因为 _instance 无法再次初始化。这只是一个想法,但我可能完全偏离,但这就是我认为正在发生的事情。

于 2010-01-11T17:20:14.710 回答
0

A static field marked with ThreadStaticAttribute is not shared between threads. Each executing thread has a separate instance of the field, and independently sets and gets values for that field. If the field is accessed on a different thread, it will contain a different value.

于 2013-11-12T11:21:47.433 回答