产生问题的示例代码:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
tg.create( () => writeln(i) );
tg.joinAll();
}
示例输出:
3
5
5
5
5
(预期输出是整数 1 到 5。)
我不明白为什么会发生这种情况 - i
不是引用类型,也没有在委托(delegate)中使用它的引用,那么为什么每个线程都使用i
作为调度线程时它恰好具有的任何值,而不是它给出的可能的按值传递值?
我已经做了一些像这样的蹩脚尝试,但没有成功:
foreach (int i; 1 .. 5) {
scope j = i;
tg.create( () => writeln(j) );
}
我也很好奇为什么这不起作用。不是每次都声明一个新的j
吗?为什么每个线程都引用相同的 j
(在线程调度时其值通常为 5)?
最佳答案
so why does each thread use the value of i as whatever value it happens to have when the thread is scheduled, instead of the presumably pass-by-value value it's given?
就循环体而言,它是按值传递的,但这不适用于在其中创建的线程。线程仍将通过其地址引用 i
。
要解决此问题,您需要在循环内创建一个闭包:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
(i =>
tg.create( () => writeln(i) )
)(i);
tg.joinAll();
}
lambda 参数将存储在闭包中,为每个线程提供自己的副本。
关于foreach - 如何让 foreach 对委托(delegate)使用非引用类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21984438/