线程似乎永远不会有机会,除非我有一个断点

时间:2012-05-19 10:18:03

标签: c# multithreading c#-4.0 locking

我尝试制作一个执行以下操作的简单程序:

我有两台起重机将集装箱从船上卸下。他们把集装箱放在码头上,那里有2/3辆卡车把它们捡起来。起重机最多可以在码头放置5个集装箱。

问题如下:当我没有断点时,起重机螺纹只挑选船的集装箱并将它们放到码头上然后程序停止。这是每次输出:

Kraan 2 heeft container nummer 1 van het schip gehaald.
Kraan 2 heeft container nummer 1 op de kade geplaatst.
Kraan 1 heeft container nummer 2 van het schip gehaald.
Kraan 1 heeft container nummer 2 op de kade geplaatst.
Kraan 2 heeft container nummer 3 van het schip gehaald.
Kraan 1 heeft container nummer 4 van het schip gehaald.
Kraan 2 heeft container nummer 3 op de kade geplaatst.
Kraan 2 heeft container nummer 5 van het schip gehaald.
Kraan 2 heeft container nummer 5 op de kade geplaatst.
Kraan 1 heeft container nummer 4 op de kade geplaatst.
Kraan 2 heeft container nummer 6 van het schip gehaald.
Kraan 1 heeft container nummer 7 van het schip gehaald.

因此,卡车线程不会运行。当我在Wagen.VoerWerkzaamhedenUit()中放置一个断点时,断点被击中并奇迹般地整个程序运行直到所有容器都被处理完毕。

这是我的代码:

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i <= 100; i++)
            {
                Schip.LaadContainerOpSchip(i);
            }

            Thread kraan1 = new Thread(new Kraan().VoerWerkzaamhedenUit);
            kraan1.Name = "Kraan 1";
            kraan1.Start();

            Thread kraan2 = new Thread(new Kraan().VoerWerkzaamhedenUit);
            kraan2.Name = "Kraan 2";
            kraan2.Start();

            Thread wagen1 = new Thread(new Wagen().VoerWerkzaamhedenUit);
            wagen1.Name = "Wagen 1";
            wagen1.Start();

            Thread wagen2 = new Thread(new Wagen().VoerWerkzaamhedenUit);
            wagen2.Name = "Wagen 2";
            wagen2.Start();

            kraan1.Join();
            kraan2.Join();
            wagen1.Join();
            wagen2.Join();

            Console.WriteLine("Press any key to continue...");
            Console.Read();
        }
    }

public class Kraan
    {
        private Random random = new Random();

        public void VoerWerkzaamhedenUit()
        {
            while (Schip.HeeftContainers())
            {
                Thread.Sleep(random.Next(1000, 6000));

                int container = Schip.VerwijderContainer();

                if (container != -1)
                {
                    Console.WriteLine("{0} heeft container nummer {1} van het schip gehaald.", Thread.CurrentThread.Name, container);

                    Thread.Sleep(random.Next(1000, 6000));

                    Kade.PlaatsContainer(container);

                    Console.WriteLine("{0} heeft container nummer {1} op de kade geplaatst.", Thread.CurrentThread.Name, container);
                }
            }
        }
    }

public static class Schip
    {
        private static List<int> containers = new List<int>();

        public static void LaadContainerOpSchip(int container)
        {
            containers.Add(container);
        }

        public static int VerwijderContainer()
        {
            lock (containers)
            {
                int container = -1;

                if (containers.Any())
                {
                    container = containers[0];

                    containers.RemoveAt(0);
                }

                return container;
            }
        }

        public static bool HeeftContainers()
        {
            lock (containers)
            {
                return containers.Any();
            }
        }
    }



public static class Kade
    {
        private static List<int> containers = new List<int>();

        public static void PlaatsContainer(int container)
        {
            lock (containers)
            {
                while (containers.Count == 5)
                {
                    Monitor.Wait(containers);
                }

                containers.Add(container);

                Monitor.PulseAll(containers);
            }
        }

        public static int VerwijderContainer()
        {    
            lock (containers)
            {
                while (containers.Count == 0)
                {
                    Monitor.Wait(containers);
                }

                int container = -1;

                if (containers.Any())
                {
                    container = containers[0];

                    containers.RemoveAt(0);
                }

                Monitor.PulseAll(containers);

                return container;
            }
        }

        public static bool HeeftContainers()
        {
            lock (containers)
            {
                return containers.Any();
            }
        }
    }

public class Wagen
    {
        private Random random = new Random();

        public void VoerWerkzaamhedenUit()
        {
            while (Kade.HeeftContainers())
            {
                Thread.Sleep(random.Next(1000, 6000));

                int container = Kade.VerwijderContainer();

                if (container != -1)
                {
                    Console.WriteLine("{0} heeft container nummer {1} van de kade gehaald.", Thread.CurrentThread.Name, container);

                    Thread.Sleep(random.Next(1000, 6000));
                }
            }
        }
    }

不,我想要使用阻止集合,我想使用List<int>; - )

2 个答案:

答案 0 :(得分:1)

当程序启动时,卡车检查码头(Kade.HeeftContainers()),然后起重机才有机会将集装箱放在码头上,以便卡车线程立即离开。然后起重机继续填满码头,直到达到5个集装箱的极限。由于卡车螺纹已经退出,码头保持满载,因此起重机螺纹停止等待Monitor.Wait(containers);

要解决这个问题,卡车需要继续运行,直到所有集装箱都通过管道。例如,您可以在码头上设置一个计数器(例如loadedContainers),并在每次从码头上卸下一个集装箱时将该计数器增加以装载到卡车上。然后在return loadedContainers == 100;吸气器中Kade.HeeftContainers

答案 1 :(得分:1)

还要了解Diagnostics命名空间......

e.g。

if(!System.Diagnostics.Debugger.IsAttached)
    if(System.Diagnostics.Debugger.Attach()) System.Diagnostics.Debugger.Break();