さまざまなスレッドがリストからエンティティを取得し、ステータスを設定して、それらのアイテムで処理が開始されたという事実をマークする、軽量のキュー処理を実装する 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;
}
これにより、一度に 1 つのスレッドだけが「もの」のステータスを変更できることが保証されると期待していましたが、ログにはかなり定期的にこれが記録されています。
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
..そして、両方のスレッドが同じことを試みて操作し、混乱を引き起こします。
私は何が欠けていますか?ありがとう。
編集:実際のバージョンでログがどのように機能するかを反映するようにコードを変更しました