2011-05-23 72 views
5

我有一個S#arp體系結構應用程序,它實現了一個輕量級的隊列處理事物,從而各種線程從列表中拉取實體並設置其狀態以標記處理已開始處理這些項目。NHibernate併發問題

儘管在顯式事務中使用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

你能解決這個問題嗎? – 2011-05-23 21:37:29

+0

沒有機會嘗試你的建議,但我會盡快給它。 – codeulike 2011-05-23 21:46:08

回答

1

設置併發在NHibernate的映射是如何工作的,這個職位應該幫助您開始。

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

+0

哇,這是否意味着所有的Nhibernate事務代碼不會做任何事情,除非併發選項設置在某個地方? – codeulike 2011-05-23 17:11:26

+0

我不確定,但如果您不想設置映射,則可以嘗試此操作。 'session.Lock(thing,LockMode.Upgrade);' – 2011-05-23 17:21:14

0

我認爲你是剛剛跨過了您正在使用設置您處理,並檢查是否已經處理狀態。第一個集合ThingStatusEnum.Processing,但下一個人正在檢查不同的東西 - ThingStatusEnum.PreProcessing。因爲ThingStatusEnum.Processing!= ThingStatusEnum.PreProcessing,你的鎖定意味着兩個線程不是

+0

但是我不明白,即使在某個地方存在邏輯問題,如果記錄器從臨界區域內記錄,記錄器又是如何報告的。這可能是記錄器本身不準確(Log4net?)。也許嘗試追加時間到日誌,看看他們是否真的碰撞,這似乎不太可能。 – Ernesto 2011-05-23 17:24:47

+0

之前沒有注意到時代完全一樣。你是對的,那確實表明它正在同時運行。應該不可能與靜態鎖定對象一起使用。與nhibernate或s#arp架構無關。無論任何數據庫交互,多個線程都不應該能夠同時運行該代碼。如果鎖定對象不是靜態的,我認爲你正在處理不同的實例,但我沒有爲你的答案。我仍然認爲檢查狀態存在缺陷,但我無法在日誌中解釋時間。 – 2011-05-23 20:55:50

+0

@ Ernesto,@ Dave - 哎呀,對不起,我在這裏發佈它時會「簡化」代碼,並移動日誌語句。在我的版本中,日誌記錄發生在鎖定之外 - 您很確定發佈的代碼不可能同時使用兩個日誌。我將編輯該問題。 – codeulike 2011-05-23 21:30:01