Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程与任务中的ThreadStatic属性_C#_Multithreading_C# 4.0_Thread Safety_Threadstatic - Fatal编程技术网

C# 线程与任务中的ThreadStatic属性

C# 线程与任务中的ThreadStatic属性,c#,multithreading,c#-4.0,thread-safety,threadstatic,C#,Multithreading,C# 4.0,Thread Safety,Threadstatic,在使用ThreadStatic属性探索线程和任务时,我遇到了一些奇怪的事情。我相信这对于线程和任务来说可能非常特殊。 考虑下面的代码片段: [ThreadStatic] static int range=10; Action action = () => {Console.WriteLine("Thread = {0}, Value = {1}", Thread.CurrentThread.ManagedThreadId, range); Parallel.I

在使用ThreadStatic属性探索线程和任务时,我遇到了一些奇怪的事情。我相信这对于线程和任务来说可能非常特殊。 考虑下面的代码片段:

[ThreadStatic]
static int range=10;


 Action action = () =>
           {Console.WriteLine("Thread = {0}, Value = {1}", Thread.CurrentThread.ManagedThreadId, range);

Parallel.Invoke( action, action);
这将提供以下输出:

Thread = 2, Value = 10 
Thread = 3, Value = 0
Thread = 6, Value = 0
Thread = 7, Value = 0
这是绝对正确的,因为ThreadStatic变量只能初始化一次,因此,第二行显示为0

但是,请考虑下面的场景:

[ThreadStatic]
static int range=10;

new Thread(() =>
{
Console.WriteLine("Thread = {0}, Value = {1}" Thread.CurrentThread.ManagedThreadId, range);
            }).Start();

new Thread(() =>
{
Console.WriteLine("Thread = {0}, Value = {1}" Thread.CurrentThread.ManagedThreadId, range);
            }).Start();
这一行给出了输出:

Thread = 2, Value = 10 
Thread = 3, Value = 0
Thread = 6, Value = 0
Thread = 7, Value = 0
无论我跨越了多少线程,我都无法真正看到“range”值被初始化并显示为10。这里初始化的范围变量在哪里?为什么在初始化静态变量时线程和任务之间存在区别


我是不是错过了一些基本的东西?提前谢谢

在第一种情况下,
range
变量已由初始化类的线程(运行静态构造函数的线程)初始化为
10
。在所有其他线程上,它将等于
0
。然后调用
Parallel。从同一个线程调用

与生成两个线程不同,
Parallel.Invoke
将在当前线程上调用第一个操作,在线程池
任务上调用第二个操作。由于它在所有操作完成后返回,因此不需要为此使用3个线程,其中一个线程被阻塞,等待其他2个线程完成

您可以找到:


您的第二个代码段生成了2个线程,因此不会从初始线程执行任何
Console.WriteLine
。在本例中,您永远不会看到
10
值。

您的[ThreadStatic]由包含此代码的类的静态构造函数初始化。由创建类实例或使用静态成员(以先到者为准)的线程执行。因此,根据定义,您创建的两个新线程永远看不到初始值

这种奇怪的行为实际上出现在第一个片段中。您没有想到的是,Parallel.Invoke()还使用调用Invoke()的线程来完成部分工作。所以它可以看到初始值。稍微重写一下代码可以向您展示:

class Test {
    [ThreadStatic]
    static int range=10;

    public static void Run() {
        Action action = () => {
            Console.WriteLine("Thread = {0}, Value = {1}", Thread.CurrentThread.ManagedThreadId, range);
        };
        Console.WriteLine("Start thread = {0}, Value = {1}", Thread.CurrentThread.ManagedThreadId, range);
        Parallel.Invoke(action, action);
    }
}
输出:

Start thread = 8, Value = 10
Thread = 8, Value = 10
Thread = 9, Value = 0
当然,这不是一个真正的问题,您不能在并行代码中使用[ThreadStatic]