C#中的简单线程[重复]

Posted

技术标签:

【中文标题】C#中的简单线程[重复]【英文标题】:Simple Threading in C# [duplicate] 【发布时间】:2012-06-19 21:32:15 【问题描述】:

可能重复:C# Captured Variable In Loop

我正在研究一些简单的线程应用程序,但我似乎无法让它工作:

class ThreadTest

    static Queue<Thread> threadQueue = new Queue<Thread>();

    static void Main()
    
        //Create and enqueue threads
        for (int x = 0; x < 2; x++)
        
            threadQueue.Enqueue(new Thread(() => WriteNumber(x)));
        

        while(threadQueue.Count != 0)
        
            Thread temp = threadQueue.Dequeue();
            temp.Start();
        

        Console.Read();
    

    static void WriteNumber(int number)
    
        for (int i = 0; i < 1000; i++)
        
            Console.Write(number);
        
    

目标基本上是把线程一个一个地添加到队列中,然后一个个地穿过队列,弹出一个线程并执行它。因为我的 for 循环中有“x

我最终得到的是 2000 个 2。我想出的两个可能的解决方案是:我错过了一些非常明显的事情,或者将变量 x 发送到 WriteNumber 函数正在执行传递引用而不是传递值,所以当线程执行他们使用最新版本的 x 而不是设置函数时的版本。但是,据我了解,变量在 C# 中默认按值传递,并且只有在参数中包含 'ref' 时才通过引用传递。

【问题讨论】:

线程队列肯定是一个不寻常的想法。 这不是一个奇怪的想法,这就是线程池在内部所做的。所以使用线程池。 线程池通常有一个任务类实例的队列,如果它们可以跟踪跟踪,则有一个固定的线程列表,可以使任务出列并执行任务。列表/队列中的微观管理线程通常会导致灾难。我已经在 SO 上看到了一些尝试——大量代码试图轮询列表中的线程是否“完成”,释放它们并创建新的线程来填充数组中的漏洞。真可怕…… 【参考方案1】:

您正在 lambda 表达式中捕获 x。在您启动线程之前,x 的值会更改为 2。您需要在循环中复制值 within

for (int x = 0; x < 2; x++)

    int copy = x;
    threadQueue.Enqueue(new Thread(() => WriteNumber(copy)));

Lambda 表达式捕获变量。即使传递给WriteNumber的值按值传递的,在线程启动之前它根本不会被调用——此时x是2。

通过在循环中制作副本,循环的每次迭代都会获得自己单独的 copy 变量“实例”,并且 不会改变值...所以由在调用WriteNumber 时,每个copy 变量仍然具有与x 相同的值。

【讨论】:

令人着迷,谢谢!看来我对 lambda 表达式还有很多研究要做!【参考方案2】:

这是因为x 的值在循环结束后被访问,到那时它是2

您需要使用临时变量来防止变量捕获。

for (int x = 0; x < 2; x++)

    int tmp = x;
    threadQueue.Enqueue(new Thread(() => WriteNumber(tmp)));

【讨论】:

以上是关于C#中的简单线程[重复]的主要内容,如果未能解决你的问题,请参考以下文章

C#中各版本的单例模式

对 C# 循环中的多线程感到困惑 [重复]

mongodb 单事务内使用多线程加速的简单例子

mongodb 单事务内使用多线程加速的简单例子

mongodb 单事务内使用多线程加速的简单例子

mongodb 单事务内使用多线程加速的简单例子