【问题标题】:Index out of bounds when create new thread with parameters?使用参数创建新线程时索引超出范围?
【发布时间】:2015-06-27 00:29:13
【问题描述】:

我正在研究关于烘焙算法的项目,但我没有 C# 中该算法的任何演示。由于这种情况,我已经转换了我在 Wikipedia 上找到的一些 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 < threads; i++)
            {
                if (ticket[i] > ticket[max]) { max = i; }
            } 

            ticket[pid] = 1+max;
            entering[pid] = false;

            for (int i = 0; i < threads; ++i)
            {
                if (i != pid)
                {
                    while (entering[i]) 
                    {
                        Thread.Yield();   
                    } 
                    while (ticket[i] != 0 && (ticket[pid] > 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 < 10; i++)
                {
                    //New code that solved my problem
                    int copy = i;
                    threadArray[i] = new Thread(() => 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";
            }
        }
    }
}

【问题讨论】:

  • 另外,是threads &gt;= 10 吗?为什么你有时使用硬编码10 而有时使用threads
  • entering 定义在哪里?
  • 输入被填充在哪里?如,您最初在哪里为其添加值,我假设它是bool[],但请显示您的声明和初始化。
  • @npinti:我刚刚更新了我的帖子。
  • 请不要将您的问题标记为SOLVED - 无论如何您接受了答案这一事实。

标签: c# multithreading indexoutofboundsexception


【解决方案1】:

这就是问题所在:

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,使用单独的自包含对象而不是 parallel arrays 等。

【讨论】:

  • 非常感谢!最后,它解决了我的问题。但是又出现了另一个问题。你能再帮我一次吗?我现在就编辑我的帖子。
  • @HuynhLePhong:你不应该编辑你原来的帖子——如果你有一个单独的问题,你应该写一个单独的问题。
  • 糟糕!看来我只能在接下来的 90 分钟内发布一个新主题。你能帮我吗 ?我刚刚更新了我的帖子。
  • @Huynh:不。花 90 分钟的时间让你的新问题尽可能好。见tinyurl.com/stack-hints
  • 嗨,Jon Skeet 先生:我已经在这里发布了:stackoverflow.com/questions/29747694/… - 但仍然没有人回答!希望这次你能帮帮我。
猜你喜欢
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 2013-10-31
相关资源
最近更新 更多