我试图了解应用程序中发生的非常奇怪的句柄泄漏。 我已设法在以下代码中找出问题所在:
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();
}
}
}
按原样,此测试应用程序非常快速地提升到23721个句柄(5秒足以达到此值)
但是,删除"抛出新的异常"在运行几分钟时,应用程序保持稳定,有大约450个手柄。
知道这里有什么问题吗?
谢谢!
编辑#1
由于问题的警告不可重现,我发现只有在Visual Studio内部以调试模式运行时才会发生这种情况(2013和2015专业版的结果相同)。
编辑#2
今天,我使用完全相同版本的Visual Studio(2013 Pro 12.0.40629.00 Update5)在另一台计算机上测试了完全相同的项目,但这一项在Windows 8.1中运行(我的计算机运行的是Windows 10) ),我无法在这里重现这个问题。
编辑#3
我刚刚在另一台运行Windows 10和Visual Studio 2015 Pro的计算机上测试过,问题确实发生了不!现在我非常困惑,因为我在Visual Studio 2015 Pro中运行时在计算机中遇到了同样的问题而且我没有安装特殊扩展。我想我会用周末来完全重新安装系统。
答案 0 :(得分:0)
由于.NET中的关键部分创建行为,可能会发生这种情况。如您所知,catch
块几乎可以保证运行,并且CLR创建了一些内部结构来完成此操作。所以我认为很多句柄都是因为这个 - 你在后台Task
运行代码,而且肯定是一些同步的内部构造。
从另一方面来看,当你处于发布模式时,为什么这不是一个问题?出于调试目的,正在编译调试模式而不进行编译器优化。发布代码正在优化,您的catch
数据块为空,因此我认为它永远不会在发布模式下运行 - 您的代码根本就不会丢弃,而且它就是它
我现在无法检查,但我认为在Release中重现问题的方法是在catch
块中添加一些代码:
try
{
throw new Exception("?");
}
catch (Exception e)
{
// log exception here
}
更新:我认为您正在衡量的不是您的应用程序的句柄数(ConsoleApplication2.exe
),而是为您自己创建的VS(ConsoleApplication2
<强> .vshost
强> .exe
)。所以这只是关于Visual Studio
。