C# NHibernate并发问题

C# NHibernate并发问题,c#,nhibernate,concurrency,sharp-architecture,C#,Nhibernate,Concurrency,Sharp Architecture,我有一个S#arp架构的应用程序,它实现了一个轻量级的队列处理功能,各种线程从列表中提取实体,并设置它们的状态,以标记处理已开始于这些项目的事实 尽管将开始处理位包装在显式事务中并使用C#lock(),但有时我仍然会让它们同时启动 我是否后悔没有使用MSMQ。。。嗯,是的,但现在这种并发行为让我感到困惑。很明显,关于NHibernate交易和刷新,有一些我不理解的地方。你能帮我吗 以下是相关的代码位: private static object m_lock = new object(); p

我有一个S#arp架构的应用程序,它实现了一个轻量级的队列处理功能,各种线程从列表中提取实体,并设置它们的状态,以标记处理已开始于这些项目的事实

尽管将开始处理位包装在显式事务中并使用C#lock(),但有时我仍然会让它们同时启动

我是否后悔没有使用MSMQ。。。嗯,是的,但现在这种并发行为让我感到困惑。很明显,关于NHibernate交易和刷新,有一些我不理解的地方。你能帮我吗

以下是相关的代码位:

private static object m_lock = new object();

private bool AbleToStartProcessing(int thingId)
{
    bool able = false;
    try
    {
        lock (m_lock)
        {
            this.thingRepository.DbContext.BeginTransaction();
            var thing = this.thingRepository.Get(thingId);
            if (thing.Status == ThingStatusEnum.PreProcessing)
            {
                able = true;
                thing.Status = ThingStatusEnum.Processing;
            }
            else
            {
                logger.DebugFormat("Not able to start processing {0} because status is {1}",
                        thingId, thing.Status.ToString());
            }
            this.thingRepository.DbContext.CommitTransaction();
        }
    }
    catch (Exception ex)
    {
        this.thingRepository.DbContext.RollbackTransaction();
        throw ex;
    }
    if (able)
        logger.DebugFormat("Starting processing of {0}",
                        thingId);
    return able;
}
我本以为这可以保证一次只有一个线程可以更改“东西”的状态,但我经常在日志中看到这一点:

2011-05-18 18:41:23,557 thread41 DEBUG src:MyApp.Blah.ThingJob - Starting processing of 78090
2011-05-18 18:41:23,557 thread51 DEBUG src:MyApp.Blah.ThingJob - Starting processing of 78090
。。然后两个线程尝试在同一个对象上操作,并造成混乱

我错过了什么?谢谢


编辑:更改代码以反映我的日志在真实版本中的工作方式

在您的NHibernate映射中设置并发性,这篇文章应该可以帮助您开始


我认为您只是被用于设置您正在处理的状态和检查您是否已经在处理的状态弄糊涂了。第一个是ThingStatusEnum.Processing,但下一个是检查不同的东西——ThingStatusEnum.PreProcessing。因为ThingStatusEnum.Processing!=ThingStatusEnum.PreProcessing,您的锁定意味着两个线程不

哇,这是否意味着所有Nhibernate事务代码都不会执行任何操作,除非在某个地方设置了并发选项?我不确定,但如果不想设置映射,您可以尝试此操作<代码>会话.锁(东西,锁模式.升级)但我不明白,即使在某个地方存在逻辑问题,如果日志记录程序是从关键部分中记录的,那么它如何在同一时间报告。可能是记录器本身不准确(Log4net?)。也许你可以试着在日志上加上时间,看看它们是否真的发生碰撞,这似乎不太可能。我以前没有注意到时间是完全一样的。你是对的,这确实表明它正在同时运行。静态锁定对象不应该是可能的。与nhibernate或s#arp架构无关。无论数据库如何交互,多个线程都不能同时运行该代码。如果lock对象不是静态的,我会认为您处理的是不同的实例,但我没有一个答案。我仍然说状态检查中存在缺陷,但我无法解释日志中的时间。@Ernesto,@Dave-oops,对不起,伙计们,我在这里发布代码时“简化”了代码,并移动了日志语句。在我的版本中,日志记录发生在锁之外——您完全正确,使用发布的代码不可能同时记录两个日志。我将编辑问题。不要认为有逻辑问题-项目开始于预处理状态,并在拾取时更改为处理。代码摘录的目的是确保在任何时候只有一个线程可以进行更改。@codeulike-我知道这是很久以前的事了,但是我回顾了一些旧的东西,发现这个问题仍然没有得到回答,看起来在你更新后我没有再访问。有了你的更新,我想说你一次只做一个。在锁之外进行日志记录时,您对同时进行日志记录没有任何限制,但实际上事务一次只进行一次。看起来你可能认为锁会阻止第二个事务的发生-如果你认为是这样,那是一个误解-它只是等待第一个事务完成,然后继续。你能弄明白这一点吗?我还没有机会尝试你的建议,但我很快就会尝试。