2012-01-09 49 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