初始化ThreadStatic现场还是引起的NullReferenceException [英] Initializing ThreadStatic field still causes NullReferenceException

查看:137
本文介绍了初始化ThreadStatic现场还是引起的NullReferenceException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了自己是一个多线程随机生成

 公共静态类MyRandGen 
{
私人静态随机GlobalRandom =新的随机();
[ThreadStatic]
私人静态随机ThreadRandom =新的随机(SeedInitializer());
私有静态诠释SeedInitializer()
{
锁(GlobalRandom)返回GlobalRandom.Next();
}

公共静态INT下一个()
{
返回ThreadRandom.Next();
}
}



然而,它抛出我的射击下一个NullReferenceException( ),我不明白。是那种初始化莫名其妙地禁止ThreadStatic领域?



我知道我可以只检查,如果该字段的初始化每一次,但是这不是我要找的解决方案。


解决方案

初始化ThreadStatic领域是有点棘手。特别是有这样的警告:




不要为字段指定初始值标有
ThreadStaticAttribute,因为这样的初始化只发生一次,
当类构造函数执行,因此只影响一个
线。




MSDN文档。这意味着,当类初始化线程运行获取初始值您在字段声明中已经定义,但所有其他线程将成为空值。我想这就是为什么你的代码是在展示你的问题描述的不良行为



一个更全面的解释是的这个博客



(从博客片段)

  [ThreadStatic] 
私人静态字符串美孚=foo的字符串;




ThreadStatic在静态构造函数初始化 - 其中只有
执行一次。因此,静态构造函数执行时只有第一个线程被指定为foo的
串。当所有的
后续线程访问,foo是留在未初始化的空值。



要解决这一点,最好的方法是使用一个属性来访问
富的道具。




  [ThreadStatic] 
私人静态字符串_foo ;

公共静态字符串美孚{
获得{
如果(_foo == NULL){
_foo =foo的字符串;
}
返回_foo;
}
}

请注意,没有必要在一个锁静态属性,因为每个线程都在演戏的 _foo ,这只是该线程。不能有争用与其他线程。这是覆盖在这个问题: ThreadStatic和同步


I've written myself a multi-threaded random generator

public static class MyRandGen
{
    private static Random GlobalRandom = new Random();
    [ThreadStatic]
    private static Random ThreadRandom = new Random(SeedInitializer());
    private static int SeedInitializer()
    {
        lock (GlobalRandom) return GlobalRandom.Next();
    }

    public static int Next()
    {
        return ThreadRandom.Next();
    }
}

However, it throws me a NullReferenceException on firing Next(), which I don't understand. Is that kind of initializing ThreadStatic fields forbidden somehow?

I know I could just check if the field's initialized every time, but that's not the solution I'm looking for.

解决方案

Initializing ThreadStatic fields is a little tricky. In particular there is this caveat:

Do not specify initial values for fields marked with ThreadStaticAttribute, because such initialization occurs only once, when the class constructor executes, and therefore affects only one thread.

in the MSDN Docs. What this means is that the thread running when the class is initialized gets that initial value you've defined in the field declaration, but all other threads will have a value of null. I think this is why your code is exhibiting the undesirable behavior described in your question.

A fuller explanation is in this blog.

(a snippet from the blog)

[ThreadStatic]
private static string Foo = "the foo string";

The ThreadStatic is initialized in the static constructor - which only executes once. So only the very first thread is assigned "the foo string" when the static constructor executes. When accessed in all subsequent threads, Foo is left at the uninitalized null value.

The best way to work around this is to use a property to access the Foo prop.

[ThreadStatic]
private static string _foo;

public static string Foo {
   get {
     if (_foo == null) {
         _foo = "the foo string";
     }
     return _foo;
   }
}

Note that there is no need for a lock in the static property, because each thread is acting upon the _foo that is just for that thread. There can't be contention with other threads. This is covered in this question: ThreadStatic and Synchronization

这篇关于初始化ThreadStatic现场还是引起的NullReferenceException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆