ThreadStatic v.s. ThreadLocal <t>:比属性?</t>更通用

时间:2013-08-20 11:29:58

标签: c# generics attributes thread-local threadstatic

[ThreadStatic]使用属性定义,而ThreadLocal<T>使用泛型。 为什么选择不同的设计方案? 在这种情况下,使用泛型over属性有哪些优点和缺点?

4 个答案:

答案 0 :(得分:90)

博客文章在评论中指出的内容并未明确,但我发现非常重要,[ThreadStatic]并未自动为每个帖子初始化内容。例如,假设你有这个:

[ThreadStatic]
private static int Foo = 42;

使用此功能的第一个帖子会将Foo初始化为42。但随后的线程不会。初始化程序仅适用于第一个线程。因此,您最终必须编写代码来检查它是否已初始化。

ThreadLocal<T>通过让您在第一次访问该项目之前提供初始化函数(如Reed的博客节目)来解决该问题。

在我看来,使用[ThreadStatic]代替ThreadLocal<T>没有任何好处。

答案 1 :(得分:31)

ThreadStatic仅在第一个线程初始化,每个线程的ThreadLocal Initialize。以下是简单演示:

    public static ThreadLocal<int> _threadlocal =
        new ThreadLocal<int>(() =>
        {
            return Thread.CurrentThread.ManagedThreadId;
        });

    public static void Main()
    {
        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("First Thread: {0}", x);
            }
        }).Start();

        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("Second Thread: {0}", x);
            }
        }).Start();

        Console.ReadKey();
    }

enter image description here

答案 2 :(得分:11)

ThreadStatic背后的主要思想是为每个线程维护变量单独副本

class Program
    {
        [ThreadStatic]
        static int value = 10;

        static void Main(string[] args)
        {
            value = 25;

            Task t1 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T1: " + value);
            });
            Task t2 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T2: " + value);
            });
            Task t3 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T3: " + value);
            });

            Console.WriteLine("Main Thread : " + value);

            Task.WaitAll(t1, t2, t3);
            Console.ReadKey();
        }
    }

在上面的代码片段中,我们为每个帖子都有一个value的单独副本,包括主线程。

enter image description here

因此,ThreadStatic变量将在其他线程上初始化为其默认值,但创建它的线程除外。

如果我们想以自己的方式在每个线程上初始化变量,请使用ThreadLocal。

答案 3 :(得分:-1)

我在同一个地方使用这两者,因为ThreadStatic仅在第一个线程上初始化,ThreadLocal为每个线程初始化。

[ThreadStatic]
    private static IOperationHolder<RequestTelemetry> operation;

    private ThreadLocal<bool> status = new ThreadLocal<bool>(true);

    //TODO: this method will move AOP start method
    public void StartOperation(string functionName)
    {
        RequestTelemetry requestTelemetry = new RequestTelemetry { Name = functionName };
        operation = telemetryClient.StartOperation(requestTelemetry);
    }