.Net Core 3.1.6线程本地/线程静态



关于C#中ThreadStaticThreadLocal的快速问题,特别是.Net Core 3.1.6.

我宁愿不发布确切的例子,但它与此非常相似:

[ThreadStatic]
static readonly Object LocalObject = new Object();

然后,我使用ParrallelEnumerableTasks.Parallel从多个不同的线程访问所述对象,遇到了一个非常有趣的异常,不幸的是,该异常导致运行时崩溃。。。

我的代码的意图是,每个访问LocalObjectThread都将有自己的实例,如所示

.Net Core 3.1.6中的ThreadLocal/ThreadStatic是否存在任何已知问题?我在哪里可以了解这些问题?

如果3.1.6没有任何变化或不同,5.0中是否有与相同属性相关的变化?如果这些都没有,那么.Net核心是否已经从它们的完整框架实现中改变了这些构造的行为?

感谢您抽出时间!

[ThreadStatic]
static Object LocalObject;

不要为用ThreadStaticAttribute标记的字段指定初始值,因为当类构造函数执行时,这种初始化只发生一次,因此只影响一个线程。如果未指定初始值,则如果字段是值类型,则可以依赖于将其初始化为默认值;如果字段是引用类型,则依赖于将字段初始化为null。

因此,我们删除readonly,并在每次访问时检查null,并将其存储到每个线程的static中。(静态构造函数仍然只运行一次(

另请参阅AsyncLocal<T>,特别是如果使用ThreadPool线程,以及处理线程静态变量

根据您在链接中提供的文档,问题是当您访问变量时,值为null,因为:

需要注意的一件事是,如果我们初始化ThreadStatic变量,例如,如果我们编写以下

[ThreadStatic]
static int value = 10;

您需要注意,这只在声明的线程上初始化,所有使用值的线程都会得到一个用默认值初始化的变量,即0。

因此,如果您试图对该变量执行某些操作,并期望该变量具有Object实例,则它将抛出一个异常,如果不进行处理,则会导致应用程序失败。

编辑-2020年7月21日

经过一些测试,我终于得出结论:由于初始化问题,该字段不能是readonly,也就是说,该字段将只为第一个线程初始化,无论是内联还是在static构造函数中。任何后续的thread将只获得一个null值。

我能得到的最接近的结果如下:

public static void Main(string[] args)
{
var tsk1 = Task.Run(() => {
new Test().Display();
});
var tsk2 = Task.Run(() => {
new Test().Display();
});
Task.WaitAll(new Task[] { tsk1, tsk2 });
}
class Test {
[ThreadStatic]
static Object _localObject;
// Creates a new instance per thread.
static Object LocalObject => _localObject ?? (_localObject = new Object());
public void Display() {
Console.WriteLine(LocalObject.GetHashCode());
} 
}
// Sample output:
// C:Test> dotnet run
// 4032828
// 6044116

相关内容

  • 没有找到相关文章

最新更新