Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
424 views
in Technique[技术] by (71.8m points)

c# - Index out of bounds when create new thread with parameters?

I'm working on my project about Bakery Algorithm but i don't have any demo of that Algorithm in C# . Because of that situation i've converted some java code that i found on Wikipedia . But Anyway , it doesn't seem to work !

Updated : Here's my full-working code ( old code include in "//" comment )

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";
            }
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is the problem:

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

You're capturing i here - the single variable which will be updated over the course of the loop, and end up with a value of threads.

If the thread only actually executes the body of the lambda expression after the loop is completed, that value will basically be inappropriate... and even if it doesn't, you could easily have multiple threads using the same value of i.

You basically want a separate variable for each iteration of the loop, e.g.

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();
}

That way each iteration of the loop captures a separate variable which has the value of i for that iteration, but which isn't then changed.

That's the smallest change between your current code and working code - but personally I'd be looking to make larger changes to use the TPL more heavily, have separate self-contained objects instead of parallel arrays etc.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...