C# 在 foreach 循环中启动一个新线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9418554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Starting a new thread in a foreach loop
提问by Kris Harper
I have a List of objects and I'd like to loop over that list and start a new thread, passing in the current object.
我有一个对象列表,我想遍历该列表并启动一个新线程,传入当前对象。
I've written an example of what I thought should do this, but it's not working. Specifically, it seems like the threads are getting overwritten on each iteration. This doesn't really make sense to me though because I'm making a new Thread object each time.
我写了一个我认为应该这样做的例子,但它不起作用。具体来说,似乎线程在每次迭代中都被覆盖了。不过这对我来说没有意义,因为我每次都在创建一个新的 Thread 对象。
This is the test code I wrote
这是我写的测试代码
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.ThreadingMethod();
}
}
class TestClass
{
public void ThreadingMethod()
{
var myList = new List<MyClass> { new MyClass("test1"), new MyClass("test2") };
foreach(MyClass myObj in myList)
{
Thread myThread = new Thread(() => this.MyMethod(myObj));
myThread.Start();
}
}
public void MyMethod(MyClass myObj) { Console.WriteLine(myObj.prop1); }
}
class MyClass
{
public string prop1 { get; set; }
public MyClass(string input) { this.prop1 = input; }
}
The output on my machine is
我机器上的输出是
test2
test2
but I expected it to be
但我希望它是
test1
test2
I tried changing the thread lines to
我尝试将线程线更改为
ThreadPool.QueueUserWorkItem(x => this.MyMethod(myObj));
but none of the threads started.
但没有任何线程启动。
I think I just have a misunderstanding about how threads are supposed to work. Can someone point me in the right direction and tell me what I'm doing wrong?
我想我只是对线程应该如何工作有误解。有人可以指出我正确的方向并告诉我我做错了什么吗?
采纳答案by Reed Copsey
This is because you're closing over a variable in the wrong scope. The solution here is to use a temporary in your foreach loop:
这是因为您在错误的范围内关闭了一个变量。这里的解决方案是在你的 foreach 循环中使用一个临时的:
foreach(MyClass myObj in myList)
{
MyClass tmp = myObj; // Make temporary
Thread myThread = new Thread(() => this.MyMethod(tmp));
myThread.Start();
}
For details, I recommend reading Eric Lippert's post on this exact subject: Closing over the loop variable considered harmful
有关详细信息,我建议阅读 Eric Lippert 关于这个确切主题的帖子:关闭循环变量被认为有害
回答by Steve Czetty
The problem is that you are using the most current value of the object inside of your closure. So, each invocation of the thread is looking at the same value. To get around this, copy the value into a local variable:
问题是您正在使用闭包内对象的最新值。因此,线程的每次调用都在查看相同的值。要解决此问题,请将值复制到局部变量中:
foreach(MyClass myObj in myList)
{
MyClass localCopy = myObj;
Thread myThread = new Thread(() => this.MyMethod(localCopy));
myThread.Start();
}
回答by Eric J.
Agree with Reed's answer (+1).
同意里德的回答(+1)。
I would add that if you are on .NET 4, you may want to look at the Task Parallel Library to solve this class of problem. Specifically for this case, have a look at Parallel.ForEach().
我想补充一点,如果您使用的是 .NET 4,您可能需要查看 Task Parallel Library 来解决此类问题。专门针对这种情况,请查看Parallel.ForEach()。
回答by Pranay Rana
if sequence is not matter than go for
如果顺序无关紧要
Parallel.ForEach(myList, obj => this.MyMethod(obj) );
回答by SolidSnake
I prefer this way:
我更喜欢这种方式:
public void ThreadingMethod()
{
var myList = new List<MyClass> { new MyClass("test1"), new MyClass("test2") };
Parallel.ForEach(myList, new ParallelOptions() { MaxDegreeOfParallelism = 100 },
(myObj, i, j) =>
{
MyMethod(myObj);
});
}
not tested though....
虽然没有测试....

