你好我试图在一个线程lambda方法中传递一个循环的当前索引并打印它。该方法将只打印索引的最后一个值。
class Program {
public static EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
public static EventWaitHandle autohandle = new EventWaitHandle(false, EventResetMode.AutoReset);
static readonly int ThreadNum=3;
static void Main(string[] args) {
object lk = new object();
new Thread(() => {
while (true) {
var key = Console.ReadKey();
if(key.Key==ConsoleKey.A) {
handle.Set();
} else {
handle.Reset();
}
Thread.Sleep(3000);
}
}).Start();
for(int i=0;i<ThreadNum;i++) {
new Thread(() => {
int val = i;
Console.WriteLine($"Thread:{val} created");
while (true) {
handle.WaitOne();
Console.WriteLine($"From thread:{val}");
Thread.Sleep(1000);
}
}).Start();
}
Console.WriteLine("Hello World!");
}
}
有人可以向我解释为什么我只得到索引的最后一个值。我理解索引被clojured(创建一个类复制索引值)但是当第一次迭代进入线程方法时它应该clojure我= 0并保持这种状态。
答案 0 :(得分:1)
我认为你看到的行为是因为循环在分配局部变量'val'之前迭代。所以当时声明
int val = i;
是第一次执行,循环已经迭代了3次,所以你将'val'设置为i的最后一个值。 当我运行它时,由于创建线程的相对速度,我得到了可变行为。 为了获得我认为你想要的行为,你需要在本地捕获循环迭代的计数,就像这样。
class Program
{
public static EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
public static EventWaitHandle autohandle = new EventWaitHandle(false, EventResetMode.AutoReset);
static readonly int ThreadNum = 3;
static void Main(string[] args)
{
object lk = new object();
new Thread(() => {
while (true)
{
var key = Console.ReadKey();
if (key.Key == ConsoleKey.A)
{
handle.Set();
}
else
{
handle.Reset();
}
Thread.Sleep(3000);
}
}).Start();
for (int i = 0; i < ThreadNum; i++)
{
int temp = i;
new Thread(() => ThreadMethod(temp)).Start();
}
Console.WriteLine("Hello World!");
}
private static void ThreadMethod(object obj)
{
int val = (int)obj;
Console.WriteLine($"Thread:{val} created");
while (true)
{
handle.WaitOne();
Console.WriteLine($"From thread:{val}");
Thread.Sleep(1000);
}
}
}