Nhibernate和流畅的Nhibernate的内存泄漏

时间:2018-07-12 08:27:55

标签: c# nhibernate fluent-nhibernate task-parallel-library castle-windsor

我有Windows服务,该服务基本上从客户那里读取消息,我们进行处理并通过HTTP / TCP / File等进行发送。该服务是用C#编写的,对于数据库交互,我使用NHibernate和TPL任务。

对于每批消息服务,都在单独的TPL任务中读取并插入SQL Server数据库中,然后在另一个TPL任务中从数据库中提取相同的消息,我们在处理后通过HTTP / TCP / File发送它们,并且我们还保存了这些记录使用NHibernate ISession进入数据库。

下面的代码

public Func<ISession> GetSession { get; set; }

[Transaction]
public string SaveInMessage(ISession session, string message)
{
    try
    {
        using (var session = GetSession()){
            session.Transaction.Begin();
            var inMessage = new InMessage();
            var task = new Task(()=> InsertToDatabase(session, inMessage));
            session.Transaction.Commit();
        }
    }
    catch(Exception ex)
    {
        session.Transaction.Rollback();
    }
}

public void InsertToDatabase(ISession session, InMessage inMessage){
    session.SaveOrUpdate(inMessage);
}

[Transaction]
public bool SaveOutMessage()
{    
    try
    {
        using (var session = GetSession()){
            session.Transaction.Begin();
            var inMessage = session.Load<InMessage>();
            var outMessage = new OutMessage();
            var task = new Task(()=> ConvertMessage(outMessage, inMessage, session));
            var task = new Task(()=> SendMessage(outMessage, session, outProtocol));
            session.Transaction.Commit();
        }
    }
    catch(Exception ex)
    {
        session.Transaction.Rollback();
    }
}

public void ConvertMessage(OutMessage outMessage, ISession session, Http url)
{
    conversion logic goes here;
}

public void SendMessage(OutMessage outMessage,ISession session,Protocol outProtocol)
{
    Sending message logic goes here;
    session.SaveOrUpdate(inMessage);
}

因此,在上面,我将Castle.Windsor用于IoC,这两种方法中使用的Transaction属性是相同的。 我一直在NHibernate和TPL中低于AggregateException以及OutOfMemoryException。

System.AggregateException: One or more errors occurred. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.ConcatArray(String[] values, Int32 totalLength)
at System.String.Concat(Object[] args)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session)
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at Service.ProcessMessage(Message message, ISession session) in C:\Project\Service\ProcessMessage.cs:line 247
at Service.ProcessMessage.<>c__DisplayClass22_0.<SendMessages>b__0(Task c) in C:\Project\Service\ProcessMessage.cs:line 74
at System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait(CancellationToken cancellationToken)
at Service.ProcessMessage.SendMessages(CancellationToken cancelToken) in C:\Project\Service\ProcessMessage.cs:line 73
---> (Inner Exception #0) System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.ConcatArray(String[] values, Int32 totalLength)
at System.String.Concat(Object[] args)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session)
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at Service.ProcessMessage.Process(Message message, ISession session) in C:\Project\Service\ProcessMessage.cs:line 247
at Service.ProcessMessage.<>c__DisplayClass22_0.<SendMessages>b__0(Task c) in C:\Project\Service\ProcessMessage.cs:line 74
at System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke()
at System.Threading.Tasks.Task.Execute()<---
LogExtension.Event => LogExtension.Event => LogExtension.LogEvent

Windows服务启动4-5小时后,出现以上错误。

感谢任何提示或帮助。

  • 我使用的.Net Framework版本是4.5
  • NHibernate版本为4.0.4.4000
  • Castle.Windsor版本是3.3.0
  • FluentNhibernate版本是1.3.0.733
  • Castle.Facilities.NHibernate版本为0.7.1.23602
  • Castle.Facilities.AutoTx版本为3.2.207.2207
  • Castle.Core版本为3.3.3

1 个答案:

答案 0 :(得分:0)

您尚未发布$Site = "ABC" $csv = Import-Csv "C:\csv.csv" ForEach ($line in $csv) { Get-CMBoundary -BoundaryName $line.Name | Where-Object{($_.Value -eq $line.Subnet) -and ($_.ShortCode -eq $Site) } | Remove-CMBoundary } 的逻辑,但给我的印象是您正在对所有消息重新使用同一会话。会议应该是短暂的。保持单个会话处于打开状态将导致一级缓存增长到性能下降并最终耗尽内存的程度。