简体   繁体   English

在任务内部抛出异常时处理泄漏

[英]Handle leak when exception is thrown inside task

I'm trying to understand a very strange handle leak that is occurring in an application. 我试图理解应用程序中发生的一个非常奇怪的句柄泄漏。 I've managed to isolate the problem in the following code: 我已设法在以下代码中隔离问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication2
{

    public class EventRaiser
    {
        public event EventHandler OnEvent;

        public void DoSomething()
        {
            Console.Write(".");

            try
            {
                throw new Exception("?");
            }
            catch (Exception e)
            {

            }

            if (OnEvent != null)
                OnEvent(this, null);
        }
    }

    public class EventConsumer
    {
        private EventRaiser m_Event;

        public EventConsumer()
        {
            m_Event = new EventRaiser();
            m_Event.OnEvent += m_Event_OnEvent;

        }

        public void Start()
        {
            m_Event.DoSomething();
        }

        private void m_Event_OnEvent(object sender, EventArgs e)
        {
            Task.Run(() => m_Event.DoSomething() ); // 4.5
            //Task.Factory.StartNew(() => m_Event.DoSomething()); // 4.0
        }
    }

    class Program
    {
        private static EventConsumer x;
        static void Main(string[] args)
        {
            x = new EventConsumer();
            x.Start();

            Console.ReadLine();
        }
    }
}

As is, this test application raises to 23721 handles very very quickly (5 seconds were enough to reach this value) 这样,这个测试应用程序非常快速地提升到23721个句柄(5秒就足以达到这个值)

任务管理器屏幕截图

However, removing the "throw new Exception" line, the application stays stable with about 450 handles while running for several minutes. 但是,删除“throw new Exception”行,应用程序在运行几分钟时保持稳定,大约有450个句柄。

Any idea what is wrong here? 知道这里有什么问题吗?

Thanks! 谢谢!

Edit #1 编辑#1

With the warnings of the problem not being reproducible, I've noticed it is happening only when running in debug mode inside Visual Studio (same result in 2013 and 2015 Professional). 由于问题的警告不可重现,我注意到只有在Visual Studio内部以调试模式运行时才会发生这种情况(2013和2015 Professional中的结果相同)。

Edit #2 编辑#2

Today, I've tested the exact same project on another computer using the exact same version of Visual Studio (2013 Pro 12.0.40629.00 Update5), but this one is running in Windows 8.1 (my computer is running Windows 10), and I was unable to reproduce the problem here. 今天,我使用完全相同版本的Visual Studio(2013 Pro 12.0.40629.00 Update5)在另一台计算机上测试了完全相同的项目,但是这一个在Windows 8.1中运行(我的计算机运行的是Windows 10),我是无法在这里重现问题。

Edit #3 编辑#3

I've just tested in another computer running Windows 10 and Visual Studio 2015 Pro and again, the problem did not occur! 我刚刚在另一台计算机上测试运行Windows 10和Visual Studio 2015年Pro和再次, 没有发生问题! Now I'm very very confused, because I'm having the same problem in my computer while running in Visual Studio 2015 Pro and I have no special extensions installed. 现在我非常困惑,因为我在Visual Studio 2015 Pro中运行时在计算机中遇到同样的问题而且我没有安装特殊扩展。 I think I'll use the weekend to completely reinstall the system. 我想我会用周末来完全重新安装系统。

That can happen because of critical section creation behaviour in .NET. 这可能是因为.NET中的关键部分创建行为。 As you know, the catch block are nearly guaranteed to run, and the CLR create some inner constructions to get this done. 如你所知, catch块几乎可以保证运行,而CLR创建了一些内部结构来完成这项工作。 So I think that the numerous handles are craeted is because of this - you run your code in Task in background, and the are definitely some inner constructions with synchronization. 所以我认为很多句柄都是因为这个 - 你在后台的Task中运行代码,而且肯定是一些同步的内部构造。

From other side, why doesn't this be a problem when you are in release mode? 另一方面,为什么在发布模式下这不是问题? Debug mode is being compiled without compiler optimization, for the debug purposes. 出于调试目的,正在编译调试模式而不进行编译器优化。 The Release code is being optimized, and your catch block is empty so I think it's never runs in Release mode - your code simply doesn't throw at all, and that's it. Release代码正在优化,你的catch块是空的,所以我认为它永远不会在Release模式下运行 - 你的代码根本就不会抛出,就是这样。

I can't check right now, but I think that the way to reproduce the problem in Release is to add some code in catch block: 我现在无法检查,但我认为在Release中重现问题的方法是在catch块中添加一些代码:

        try
        {
            throw new Exception("?");
        }
        catch (Exception e)
        {
            // log exception here
        }

Update : I think that you are measuring number of handles not for your application ( ConsoleApplication2.exe ), but for VS created for you for run from itself ( ConsoleApplication2 .vshost .exe ). 更新 :我认为您正在测量的不是您的应用程序的句柄数( ConsoleApplication2.exe ),而是为您自己运行的VS( ConsoleApplication2 .vshost .exe )。 So this is only about the Visual Studio . 所以这只是关于Visual Studio

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM