首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >初始化ThreadStatic字段仍会导致NullReferenceException

初始化ThreadStatic字段仍会导致NullReferenceException
EN

Stack Overflow用户
提问于 2013-08-07 01:03:27
回答 2查看 9.9K关注 0票数 50

我给自己写了一个多线程随机生成器

代码语言:javascript
复制
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();
    }
}

但是,它在触发Next()时抛出了一个NullReferenceException,我不明白。这种初始化ThreadStatic字段是不是被禁止了?

我知道我可以检查字段是否每次都被初始化,但这不是我想要的解决方案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-07 01:18:34

初始化ThreadStatic字段有点棘手。特别要注意的是:

不会为标记为ThreadStaticAttribute的字段指定初始值,因为此类初始化只在类构造函数执行时发生一次,因此只影响一个线程。

MSDN Docs中。这意味着在初始化类时运行的线程将获得您在字段声明中定义的初始值,但所有其他线程的值都将为null。我认为这就是为什么你的代码会表现出你问题中描述的不受欢迎的行为。

更完整的解释在this blog中。

(摘自博客)

代码语言:javascript
复制
[ThreadStatic]
private static string Foo = "the foo string";

在静态构造函数中初始化ThreadStatic -该构造函数只执行一次。因此,当静态构造函数执行时,只有第一个线程被分配了“foo字符串”。当在所有后续线程中访问时,Foo将保留未初始化的空值。

解决这个问题的最好方法是使用属性来访问Foo prop。

代码语言:javascript
复制
[ThreadStatic]
private static string _foo;

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

请注意,不需要在静态属性中设置锁,因为每个线程都会根据专用于该线程的_foo进行操作。不能与其他线程争用。这在这个问题中有涉及:ThreadStatic and Synchronization

票数 77
EN

Stack Overflow用户

发布于 2019-06-08 07:43:42

关于问题的原因,前面的答案是正确的。

如果您可以使用.NET 4或更高版本,请使用ThreadLocal,因为它是通过初始化器构建的。

请参阅ThreadStatic v.s. ThreadLocal: is generic better than attribute?

这样你就不需要在每次读取时都进行访问器重载或null检查。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18086235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档