MediaPlayer中的内存泄漏

时间:2015-05-29 18:08:24

标签: c# multithreading garbage-collection threadpool

有人可以解释为什么以下程序内存不足吗?

class Program
{
    private static void ThreadRoutine()
    {
        System.Windows.Media.MediaPlayer player = new System.Windows.Media.MediaPlayer();
    }

    static void Main(string[] args)
    {
        Thread aThread;
        int iteration = 1;

        while (true)
        {
            aThread = new Thread(ThreadRoutine);
            aThread.Start();
            aThread.Join();

            Console.WriteLine("Iteration: " + iteration++);
        }
    }
}

公平地说,我得到的具体例外是System.ComponentModel.Win32Exception,"没有足够的存储空间来处理此命令。"尝试创建新的MediaPlayer时会发生异常。

MediaPlayer未实现IDisposable接口,因此我不确定是否需要进行其他清理。我当然没有在MediaPlayer文档中找到任何内容。

2 个答案:

答案 0 :(得分:1)

很久以前我有一个应用程序,它将数据渲染成图像,然后将其放在PictureBox上,就像图形引擎的管道一样,......

与你共同的东西,是缺乏记忆,就像这样,......

  • 66%
  • 67%
  • 68%
  • 69%
  • 70%
  • 71%
  • 72%
  • 73%
  • 74%
  • 70% - >自动垃圾回收
  • 71%
  • 72%
  • 73%
  • 74%
  • 75%
  • 76%
  • 77%
  • 78%
  • 79%
  • 80%
  • 81%
  • 77% - >自动垃圾回收
  • 78%
  • 79%

很多 Auto Garbage Collecting 在高内存大约90%到97%,... 但似乎还不够,在某些时候,97%和98%的系统(应用程序)崩溃了内存问题......

所以我提出这个想法,每隔几帧调用一次垃圾收集器, 所以我这样做了: 所以GC.Collect();

GC.Collect它自己很重,当内存中的对象太多时......,但是当你没有留下太多的物体时,它会顺利运行,...

关于最终确定对象也有很多事情,但我不确定它们是否正常工作,因为它们自然会以 - > x = null

这意味着,我们打破了与该对象的链接,但并不意味着我们没有将此对象放在galaxy周围的某个位置(例如,您可以使用消息填充对象析构函数,并在离开该对象后看到它赢了' t立刻被销毁,直到你关闭你的应用程序/调用GC.Collect / Lack on memory,或者随机自动收集),...直到它被销毁,...所以,例如作为“using”指令,它自称为“Dispose”方法,我们用obj = null填充我们的处理,...然后我不确定我是否应该建议你编写手动finalize方法,但还有一件事......有一个Marshal对象,我不知道它来自哪里,如果它适用于所有对象,我看到一些程序员使用它来释放对象,...,我不知道它是如何工作的,但它可能真的释放了对象从我们的记忆中......,

如果你没有找到任何有用的东西,我的第一个选择是调用GC.Collect ......

你也可以设置它的参数,因此它收集的对象少于正常情况。

https://msdn.microsoft.com/en-us/library/xe0c2357%28v=vs.110%29.aspx

Release resources in .Net C#

我也没有完全阅读,但似乎他有线程和内存问题: Freeing resources when thread is not alive

答案 1 :(得分:0)

我的 guess 是创建的Thread对象没有及时收集垃圾。

正如您在评论中指出的那样,在寻找不会导致内存泄漏的解决方案方面运气不佳,我将此替代方案发布为即使它没有尝试回答你原来的问题,也要回答。

如果您使用ThreadPool,它(a)运行得更快,(b)不会崩溃。

class Program
{
    private static void ThreadRoutine(object state)
    {
        var player = new MediaPlayer();

        var iteration = (int)state;
        if (iteration % 1000 == 0)
        {
            Console.WriteLine("Executed: " + state);
        }
    }

    static void Main(string[] args)
    {
        for (int i = 0; i < 10000000; i++)
        {
            if (i % 1000 == 0)
            {
                Console.WriteLine("Queued: " + i);
            }

            ThreadPool.QueueUserWorkItem(ThreadRoutine, i);
        }
    }
}

在我的机器上,我可以在几秒钟内创建1000万个线程池线程。

Queued: 9988000
Queued: 9989000
Queued: 9990000
Queued: 9991000
Executed: 9989000
Executed: 9990000
Executed: 9991000
Executed: 9988000
Queued: 9992000
Executed: 9992000
Queued: 9993000
Queued: 9994000
Queued: 9995000
Executed: 9994000
Executed: 9993000
Queued: 9996000
Executed: 9996000
Executed: 9995000
Queued: 9997000
Executed: 9997000
Queued: 9998000
Executed: 9998000
Queued: 9999000
Executed: 9999000
Press any key to continue . . .