Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# System.Threading.Timer windows服务内存泄漏_C#_.net_Memory Leaks_Timer_Windbg - Fatal编程技术网

C# System.Threading.Timer windows服务内存泄漏

C# System.Threading.Timer windows服务内存泄漏,c#,.net,memory-leaks,timer,windbg,C#,.net,Memory Leaks,Timer,Windbg,我有一个c控制台应用程序作为windows服务运行。应用程序的主线程使用System.Threading.Timer来管理数据库的“扫描”。当扫描在计时器刻度上开始时,计时器将创建一个对象以在数据库中查找工作,当发现工作从作业衍生到另一个线程时,该对象将引发一个事件 我似乎正在遭受内存泄漏,我有限的windbg查询内存转储的能力让我认为计时器没有向GC释放某些东西/自身 windbg: 简化和压缩代码: TimeSpan timerInterval = TimeSpan.FromSeconds(

我有一个c控制台应用程序作为windows服务运行。应用程序的主线程使用System.Threading.Timer来管理数据库的“扫描”。当扫描在计时器刻度上开始时,计时器将创建一个对象以在数据库中查找工作,当发现工作从作业衍生到另一个线程时,该对象将引发一个事件

我似乎正在遭受内存泄漏,我有限的windbg查询内存转储的能力让我认为计时器没有向GC释放某些东西/自身

windbg:

简化和压缩代码:

TimeSpan timerInterval = TimeSpan.FromSeconds(5);
static Timer t;
public void startTimer()
{
    t = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, timerInterval);
}
public void TimerTick(Object TimerState)
{
    //run each query sweep synchronously
    t.Change(Timeout.Infinite, Timeout.Infinite);
    List<Query> queries = GetQueries();
    foreach (var query in queries)
    {
        var search = new QueryProcessor(query);
        //short term publisher?
        search.resultFoundEvent += QueryResultEventListener;
        search.RunSearch();
    }
    t.Change(timerInterval, timerInterval);
}
public void RunJob(JobDetails job)
{
    Task.Factory.StartNew(() => job.Execute(JobCallback));
}
//long term subscriber
public void QueryResultEventListener(object sender, FakeEventArgs e)
{
    RunJob(e.jobdetails);
}
public void JobCallback(JobDetails jobsuccess)
{
    //job was completed
}

正如上面所评论的,我不认为这是一个传统的事件处理程序泄漏,而上面的windbg在其底部只有一个巨大的条目!dumpheap-System.Object[]的stat。

使用jetBrains dotMemory,我能够确定打开的句柄来自从job.Execute堆栈中引用的托管代码调用的代码行。它全局设置了一个委托,并导致ServerCertificateValidationCallback锁定了一个句柄而从未释放

ServicePointManager.ServerCertificateValidationCallback+=发送方、证书、链、sslPolicyErrors=>{};
感觉它的行为类似于短期发布者、长期订阅者经典内存泄漏方式,因为调用此行的构造函数的父对象不久就被释放。

您是否执行了GC.collect,在转储之前是否等待PendingFinalizers?@此windbg基于客户端计算机上运行的应用程序的taskmanager的内存转储。上面的代码是生产中运行的代码的简化版本,但它们都没有显式地调用GC。问题是,很难说这是等待清除的垃圾还是泄漏。我以前从未使用过windbg,在担心泄漏之前,它的相关信息您可以使用JetBrains dotMemory以更方便的方式分析内存转储可能其他内存分析器也可以,不知道。@Ed.ward感谢您的建议,此工具在帮助我方面绝对优于其他工具
TimeSpan timerInterval = TimeSpan.FromSeconds(5);
static Timer t;
public void startTimer()
{
    t = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, timerInterval);
}
public void TimerTick(Object TimerState)
{
    //run each query sweep synchronously
    t.Change(Timeout.Infinite, Timeout.Infinite);
    List<Query> queries = GetQueries();
    foreach (var query in queries)
    {
        var search = new QueryProcessor(query);
        //short term publisher?
        search.resultFoundEvent += QueryResultEventListener;
        search.RunSearch();
    }
    t.Change(timerInterval, timerInterval);
}
public void RunJob(JobDetails job)
{
    Task.Factory.StartNew(() => job.Execute(JobCallback));
}
//long term subscriber
public void QueryResultEventListener(object sender, FakeEventArgs e)
{
    RunJob(e.jobdetails);
}
public void JobCallback(JobDetails jobsuccess)
{
    //job was completed
}