我有一个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
..然后两个线程尝试对同一个事情进行操作并造成混乱。
我错过了什么?感谢。
编辑:更改了代码以反映我的日志记录在真实版本中的工作原理
答案 0 :(得分:1)
在NHibernate映射中设置并发性,这篇文章应该可以帮助您入门。
答案 1 :(得分:0)
我认为您只是在用于设置正在处理的状态,并检查您是否已在处理。第一个集ThingStatusEnum.Processing,但下一个人正在检查不同的东西 - ThingStatusEnum.PreProcessing。因为ThingStatusEnum.Processing!= ThingStatusEnum.PreProcessing,你的锁定意味着两个线程不是