2014-02-24 46 views
4

示例代碼產生的問題:你如何使foreach對代表使用非引用類型?

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 

(預期輸出到5是整數1)

我不明白這是爲什麼發生 - i不是引用類型,也沒有引用它在委託中使用,那麼爲什麼每個線程都使用值i作爲線程調度時發生的任何值,而不是e大概是按價值傳遞的價值?

我做瘸子嘗試這樣極少數的,但什麼也沒有成功:

foreach (int i; 1 .. 5) { 
    scope j = i; 
    tg.create(() => writeln(j)); 
} 

我很好奇,爲什麼這是不行的,無論是。是不是每次都宣佈新鮮的j?爲什麼每個線程都指向相同的j(在線程調度時它的值通常是5)?

回答

6

那麼爲什麼每個線程都使用它的值作爲它在線程調度時發生的任何值,而不是按給定的值傳遞值?

就循環體而言,它是按值傳遞的,但不適用於在其中創建的線程。線程仍然會通過其地址引用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(); 
} 

拉姆達參數將被存儲在封閉,給每個線程它自己的拷貝。

相關問題