使用参数创建新线程时索引超出范围?

我正在研究关于烘焙算法的项目,但我没有在C#中使用该算法的任何演示。 由于这种情况,我已经转换了一些我在维基百科上找到的java代码。 但无论如何,它似乎不起作用!

更新 :这是我的全部工作代码(旧代码包含在“//”注释中)

namespace BakeryAlgorithm { class Program { static int threads = 10; static string x = ""; static int count = 0; static int[] ticket = new int[threads]; static bool[] entering = new bool[threads]; public static void doLock(int pid) { entering[pid] = true; int max = 0; for (int i = 0; i  ticket[max]) { max = i; } } ticket[pid] = 1+max; entering[pid] = false; for (int i = 0; i  ticket[i] || (ticket[pid] == ticket[i] && pid > i))) { Thread.Yield(); } } } if (x == "C" || x == "c") Console.WriteLine("[System] PID " + pid.ToString() + " get into critical section"); } public static void unlock(int pid) { ticket[pid] = 0; count++; Console.WriteLine("[Thread] PID " + pid.ToString() + " process completed"); } public static void arrayInit() { for (int i = 0; i < threads; i++) { ticket[i] = 0; entering[i] = false; } } public static void simThread(int i) { doLock(i); if (x == "C" || x=="c") Console.WriteLine("[Thread] PID " + i.ToString() + " begin to process..."); Random rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF); int a = rand.Next(5,10); int b = rand.Next(1,5); int c = rand.Next(1,4); double d = 0; string o=""; if (c == 1) { d = a + b; o=" + "; } else if (c == 2) { d = a * b; o=" * "; } else if (c == 3) { d = a / b; o=" / "; } else { d = a - b; o=" - "; } if (x == "C" || x == "c") Console.WriteLine("Result of PID " +i.ToString() +" : " + a.ToString() + o + b.ToString() + "=" + d.ToString()); unlock(i); } [STAThread] static void Main(string[] args) { arrayInit(); string choice="C"; while (choice == "C" || x == "c") { Console.WriteLine("Do you want to see progress log ? (C=Yes,K=No) : "); x = Console.ReadLine(); if (x == "") x = "C"; Console.Clear(); Console.WriteLine("----------------------------------"); Console.WriteLine("Bakery Algorithm in C#"); Console.WriteLine("Number of threads : " + threads.ToString()); Console.WriteLine("Progress Log"); Console.WriteLine("----------------------------------"); Thread[] threadArray = new Thread[threads]; for (int i = 0; i  simThread(copy)); //My old code that cause my problem //threadArray[i] = new Thread(() => simThread(i)); if (x == "C" || x == "c") Console.WriteLine("[System] PID " + i.ToString() + " has been created"); threadArray[i].Start(); Thread.Sleep(20); } Console.ReadLine(); Console.WriteLine("----------------------------------"); Console.WriteLine("Process completed " + count.ToString() + " threads !"); count = 0; Console.WriteLine("----------------------------------"); Console.WriteLine("Do you want to restart the algorithm (C=Yes,K=No)"); choice = Console.ReadLine(); if (choice == "") choice = "C"; } } } } 

这就是问题:

 threadArray[i] = new Thread(() => simThread(i)); 

你在这里捕获i – 在循环过程中将更新的单个变量,最后得到一个threads值。

如果线程在循环完成实际上只执行了lambda表达式的主体,那么该值基本上是不合适的……即使它没有,你也可以轻松地使用相同的i值。

你基本上想要循环的每次迭代都有一个单独的变量,例如

 for (int i = 0; i < threads; i++) { int copy = i; threadArray[i] = new Thread(() => simThread(copy)); Console.WriteLine("[He Thong] PID " + i.ToString() + " duoc khoi tao"); threadArray[i].Start(); } 

这样,循环的每次迭代都会捕获一个单独的变量,该变量的值为i ,但不会随后更改。

这是您当前代码和工作代码之间的最小变化 – 但我个人希望进行更大的更改以更多地使用TPL,具有单独的自包含对象而不是并行数组等。