C# 播放监视器时出现内存不足异常。请等待监视器。脉冲

C# 播放监视器时出现内存不足异常。请等待监视器。脉冲,c#,out-of-memory,wait,monitor,pulse,C#,Out Of Memory,Wait,Monitor,Pulse,我在.NET中玩Monitor类,所以我得到了一段代码,它似乎正在工作,但当我循环它一段时间时,它抛出了一个OutOfMemoryException 我在一台64位Windows8开发人员机器上运行这个程序,该机器有8GB的RAM,我认为这个程序在RAM上占用的空间不会超过100MB 这是我的代码: using System; using System.Threading; public class Program { public static

我在.NET中玩Monitor类,所以我得到了一段代码,它似乎正在工作,但当我循环它一段时间时,它抛出了一个
OutOfMemoryException

我在一台64位Windows8开发人员机器上运行这个程序,该机器有8GB的RAM,我认为这个程序在RAM上占用的空间不会超过100MB

这是我的代码:

    using System;
    using System.Threading;

    public class Program
    {
        public static void Main()
        {
            while (true) {

                object theLock = new Object();
                Thread threadA = new Thread(() =>
                {
                    Console.WriteLine("Thread A before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread A locking, about to Wait");
                        Monitor.Wait(theLock);
                    }
                    Console.WriteLine("Thread A after lock");
                });

                Thread threadB = new Thread(() =>
                {
                    Console.WriteLine("Thread B before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread B lockint, about to Pulse");
                        Monitor.Pulse(theLock);
                    }
                    Console.WriteLine("Thread B before lock");
                });

                threadA.Start();
                threadB.Start();

                GC.Collect();

            }
        }
    }
我了解到这可能是一个碎片问题,并在最后添加了
GC.Collect()
。然而,我没有分配大块的空间

然后,我决定测量循环在抛出异常和添加计数器之前大约经过了多少次迭代:

    using System;
    using System.Threading;

    public class Program
    {
        public static void Main()
        {
            int counter = 0;

            while (true) {
                Console.WriteLine(counter);
                counter++;

                object theLock = new Object();
                Thread threadA = new Thread(() =>
                {
                    Console.WriteLine("Thread A before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread A locking, about to Wait");
                        Monitor.Wait(theLock);
                    }
                    Console.WriteLine("Thread A after lock");
                });

                Thread threadB = new Thread(() =>
                {
                    Console.WriteLine("Thread B before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread B lockint, about to Pulse");
                        Monitor.Pulse(theLock);
                    }
                    Console.WriteLine("Thread B before lock");
                });

                threadA.Start();
                threadB.Start();

                GC.Collect();

            }
        }
    }

这似乎大大减慢了异常的抛出速度。我测量了36000次迭代。

对于每一对线程,如果线程A在线程B之前获得了锁,那么最后两个线程都完成了,所有的事情都可以清理

如果线程B在线程A之前成功地获取了锁,那么线程B将完成(对监视器进行了脉冲处理),但是线程A将获取监视器,并永远等待有东西对其进行脉冲处理。因此,在这一点上,您将有:

  • 线程
    对象
  • 操作系统线程
  • 线程正在等待的对象
。。。基本上,所有这些都是永远捆绑在一起的

有鉴于此,我对你看到问题并不感到惊讶


目前还不清楚你想达到什么目的,但这可以解释症状。千万不要因为在
threadB.Start()
之前调用
threadA.Start()
,就认为第一个线程实际上会在第二个线程之前到达代码中的某个点。

对于每一对线程,如果线程a在线程B之前获得锁,那么两个线程都会完成,一切都可以清理干净

如果线程B在线程A之前成功地获取了锁,那么线程B将完成(对监视器进行了脉冲处理),但是线程A将获取监视器,并永远等待有东西对其进行脉冲处理。因此,在这一点上,您将有:

  • 线程
    对象
  • 操作系统线程
  • 线程正在等待的对象
。。。基本上,所有这些都是永远捆绑在一起的

有鉴于此,我对你看到问题并不感到惊讶


目前还不清楚你想达到什么目的,但这可以解释症状。千万不要因为在
threadB.Start()
之前调用
threadA.Start()
,就认为第一个线程实际上会在第二个线程之前到达代码中的某个点。

如果我注释掉脉冲行,我会得到相同的行为,这似乎就是问题所在。谢谢。此外,我并不是在试图实现任何目标,我只是在玩弄而已。如果我把脉搏线注释掉,我会得到同样的行为,这似乎就是问题所在。谢谢。我也不是在努力实现任何目标,我只是在玩。