由 Bus.Publish() 或订阅引起的 StackOverflowException?

发布于 2024-12-26 02:17:08 字数 2705 浏览 0 评论 0原文

我有一个代理,它使用传奇来跟踪给定类型的传入消息,直到收到超时消息。在超时处理程序中,我有以下内容:

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; }
    }

如果我没有任何订阅,则 Bus.Publish() 调用会顺利进行。如果我订阅了另一个服务,则会收到以下错误消息:

MSCORlib.dll 中出现类型为“System.StackOverflowException”的未处理异常

除此以外没有关于溢出的更多信息:{无法计算表达式,因为当前线程处于堆栈溢出状态。}

我有自己的 SagaPersister、Profile 和 SagaRegistry,但不确定它们是否与此问题相关,但可以在需要时提供它们。

I have an agent that employs a saga to track incoming messages of a given type until a Timeout message is received. In the Timeout handler, I have the following:

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 is an ICollection

Here is TransactionDetail class:

   [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; }
    }

If I don't have any subscriptions in place, the Bus.Publish() call goes through fine. If I have another service subscribed to it, I get the following error message:

An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

There is no further information on the overflow other than this: {Cannot evaluate expression because the current thread is in a stack overflow state.}

I have my own SagaPersister, Profile and SagaRegistry but not sure if they are pertinent to this issue but can supply them if needed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

铁憨憨 2025-01-02 02:17:08

这里看起来有点可疑的一件事是 TransactionDetail 对象上的 BankRequestResponseSagaBase Parent 属性。可能是您的引用中有一个循环,导致您的传奇持久化程序崩溃。

The one thing that looks a bit suspicious here is the BankRequestResponseSagaBase Parent property on your TransactionDetail object. It could be that you have a loop in your references that is causing your saga persister to blow up.

桃酥萝莉 2025-01-02 02:17:08

堆栈溢出通常是由可重入代码(可能是间接调用自身的方法)引起的。每次调用方法时,它都会在堆栈上使用更多的空间,因此如果它调用自身,则可能会创建一个无限循环用完所有堆栈)。

.net 中可能存在错误,但更有可能的是,您的 TimeOut 事件处理程序正在调用某些内容,导致在处理第一个事件时再次调用 Timeout,从而导致另一次调用,依此类推,从而导致无限环形。您是否在输出日志中收到大量“已超时”文本?

避免这种情况的方法是:

  • 不要进行导致重入的调用
  • 在事件处理程序执行任何工作之前删除事件订阅(并且可能在从处理程序退出时重新订阅它)
  • 使用 bool 变量或其他互锁来检测可重入调用

A stack overflow is usually caused by re-entrant code (a method that calls itself, possibly indirectly. Each time a method is called, it uses a bit more space on the stack, so if it calls itself it can create an infinite loop which uses up all the stack).

It is possible there is a bug in .net, but it's more likely that your TimeOut event handler is calling something that causes another call to Timeout while it is still processing the first one, which causes another call, and so on, causing an infinite loop. Are you getting an enormous amount of "Timeout received" text in your output log?

Ways to avoid this situation are:

  • Don't make the calls that cause the reentrancy
  • remove the event subscription in your event handler before it does any work (and possibly resubscribe it on exit from your handler)
  • use a bool variable or other interlock to detect re-entrant calls
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文