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#中的简单线程[重复]的主要内容,如果未能解决你的问题,请参考以下文章