2012-01-09 37 views
1

我有一個代理,它使用傳奇追蹤給定類型的傳入消息,直到收到超時消息。在超時處理程序,我有以下幾點:由Bus.Publish()或訂閱引起的StackOverflowException?

public override void Timeout(object state) 
     { 
      // If Data.IsNull: Do nothing!!! Report to log only. 
      Logger.Debug("========================================================================="); 
      Logger.Debug(string.Format("Timeout message received. State: {0}.", state.ToString())); 

      QuickBatch qbBuilder = new QuickBatch(); 
      // Create new message and publish it 
      BankRequestBatchClosed eventMessage = Bus.CreateInstance<BankRequestBatchClosed>(); 

      eventMessage.UniqueBatchIdentifier = qbBuilder.GenerateUniqueBatchIdentifier(QuickBatch.QB_BATCHTYPE_CC); 
      eventMessage.ScheduleBatchID = this.Data.ScheduleBatchID; 
      eventMessage.EventDate = DateTime.Now; 
      eventMessage.EventID = Guid.NewGuid(); 
      eventMessage.TransactionItems = this.Data.PaymentRequestedTransactionItems; 

      Logger.Debug("========================================================================="); 
      Logger.Debug(string.Format("Timeout method about to send BankRequestBatchClosed message. UniqueBatchIdentifier: {0}",eventMessage.UniqueBatchIdentifier)); 

      Bus.Publish(eventMessage); 
      Complete(); 
     } 

TransactionItems是一個ICollection的

這裏是TransactionDetail類:

[Serializable] 
    public class TransactionDetail 
    { 
     // Guid needed for NHibernate to store it in database. All 
     // member variables are virtual for the same reason. 
     public virtual Guid Id { get; set; } 
     public virtual Int32 ScheduleBatchID { get; set; } 
     public virtual Int32 PseudoSagaID { get; set; } 
     public virtual String CreditCardNumber { get; set; } 
     public virtual String ExpiryDate { get; set; } 

     public virtual String AccountNumber { get; set; } 
     public virtual String BSB { get; set; } 

     public virtual Decimal Amount { get; set; } 
     public virtual Int32 Firm_fk { get; set; } 
     public virtual String FirmName { get; set; } 
     public virtual TransactionType PaymentType { get; set; } 
     // transaction number, max 15 chars, to use one of the following: 
     public virtual int ApplicationPaymentInfo_fk { get; set; } 
     public virtual BankRequestResponseSagaBase Parent { get; set; } 
    } 

如果我沒有到位任何訂閱,巴士.Publish()調用正常。如果我有其他的服務訂閱了它,我收到以下錯誤信息:

類型「System.StackOverflowException」未處理的異常出現在mscorlib.dll

上有比這其他溢出沒有進一步的信息:{因爲當前線程處於堆棧溢出狀態,所以無法評估表達式。}

我有自己的SagaPersister,Profile和SagaRegistry,但不確定它們是否與此問題相關,但可以在需要時提供它們。

回答

2

一兩件事,看起來有點可疑這裏是BankRequestResponse您的TransactionDetail對象上的SagaBase Parent屬性。這可能是因爲你的參考文獻中有一個循環,這會導致你的傳奇持續者被炸燬。

+0

我刪除了參考,整理了一些其他線,它停止崩潰。感謝Udi,會盡力在悉尼見到你。 – Fellmeister 2012-01-19 00:09:16

2

堆棧溢出通常是由重入代碼引起的(一種可能間接調用自身的方法,每次調用一個方法時,它會在堆棧上佔用更多的空間,所以如果它自己調用它,它可以創建一個耗盡所有堆棧的無限循環)。

有可能在.net中有一個錯誤,但它更有可能是您的TimeOut事件處理程序正在調用導致另一個調用Timeout的事件,而它仍在處理第一個調用,這會導致另一個調用,等等,造成無限循環。您是否在輸出日誌中獲得了大量的「Timeout received」文本?

方法來避免出現這種情況是:

  • 不要做出導致重入
  • 刪除事件訂閱在事件處理它做任何工作之前(也可能重新訂閱它退出時調用從您的處理程序)
  • 使用布爾變量或其他聯鎖檢測重入調用
+0

你rpost已經在我寫的另一個應用程序中有用。感謝您分享它的時間。 – Fellmeister 2012-01-19 00:14:38