Проблема параллелизма NHibernate
У меня есть приложение 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
... а затем оба потока пытаются работать с одним и тем же и создают беспорядок.
Что мне не хватает? Благодарю.
изменить: изменил код, чтобы отразить, как моя регистрация работает в реальной версии
2 ответа
Настройте параллелизм в ваших отображениях NHibernate, этот пост должен помочь вам начать работу.
Я думаю, что вы только что получили статус, который вы используете, чтобы установить, что вы обрабатываете, и чтобы проверить, что вы уже обрабатываете. первый в наборе ThingStatusEnum.Processing, но следующий парень проверяет что-то другое - ThingStatusEnum.PreProcessing. потому что ThingStatusEnum.Processing!= ThingStatusEnum.PreProcessing, ваша блокировка означает, что два потока не являются