5

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

尽管将启动处理位包装在显式事务中并使用 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

..然后两个线程都尝试对同一事物进行操作并造成混乱。

我错过了什么?谢谢。

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

4

2 回答 2

1

在您的 NHibernate 映射中设置并发,这篇文章应该可以帮助您入门。

http://ayende.com/blog/3946/nhibernate-mapping-concurrency

于 2011-05-23T17:06:21.357 回答
0

我认为您只是对用于设置您正在处理的状态并检查您是否已经在处理的状态进行了交叉。集合中的第一个 ThingStatusEnum.Processing,但下一个人正在检查不同的东西 - ThingStatusEnum.PreProcessing。因为 ThingStatusEnum.Processing != ThingStatusEnum.PreProcessing,你的锁定意味着两个线程不是

于 2011-05-23T17:13:00.680 回答