StackOverflowException вызвано Bus.Publish () или подпиской? - PullRequest
1 голос
/ 09 января 2012

У меня есть агент, который использует сагу для отслеживания входящих сообщений определенного типа, пока не получено сообщение Timeout.В обработчике Timeout у меня есть следующее:

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 () проходит нормально.Если у меня есть другая служба, подписанная на нее, я получаю следующее сообщение об ошибке:

Произошло необработанное исключение типа 'System.StackOverflowException' в mscorlib.dll

Больше нет информации опереполнение, отличное от этого: {Невозможно оценить выражение, поскольку текущий поток находится в состоянии переполнения стека.}

У меня есть свои собственные SagaPersister, Profile и SagaRegistry, но я не уверен, имеют ли они отношение к этой проблеме, но может предоставить ихесли нужно.

Ответы [ 2 ]

2 голосов
/ 09 января 2012

Единственное, что здесь выглядит несколько подозрительно, - это свойство BankRequestResponseSagaBase Parent для вашего объекта TransactionDetail. Возможно, в ваших ссылках есть петля, из-за которой ваша история продолжает взрываться.

2 голосов
/ 09 января 2012

Переполнение стека обычно вызывается повторяющимся кодом (метод, который вызывает себя, возможно, косвенно. Каждый раз, когда вызывается метод, он использует немного больше места в стеке, поэтому, если он вызывает сам себя, он может создатьбесконечный цикл, который использует весь стек).

Возможно, есть ошибка в .net, но более вероятно, что ваш обработчик событий TimeOut вызывает что-то, что вызывает другой вызов Timeout, пока он еще обрабатываетпервый, который вызывает другой вызов, и так далее, вызывая бесконечный цикл.Получаете ли вы огромное количество текста «Время ожидания получено» в выходном журнале?

Способы избежать этой ситуации:

  • Не совершайте звонки, которые вызывают повторное появление
  • удалить подписку на событие в вашем обработчике событий до того, как она выполнит какую-либо работу (и, возможно, повторно подписать ее при выходе из вашего обработчика)
  • использовать переменную bool или другую блокировку для обнаружения повторных входящих вызовов
...