Вопрос

У меня есть небольшой пример кода:

private void MonitorItems()
        {
            if (someCondition)
            {
                dateSelected = DateTime.Now;
                GetAllItems();
            }
            else
            {
                if(allItems.Count>0)
                    CheckAllItems();
            }
            MonitorItems();
        }

Метод GetAllItems отправляется в БД и получает все новые элементы для коллекции - > все элементы. Затем метод CheckAllItems:

private void CheckAllItems()
        {
            foreach (Item a in new List<Item>(allItems))
            {
                switch (a.Status)
                {
                    case 1:
                        HandleStatus1();
                        break;
                    case 2:
                        HandleStatus2(a);
                        break;
                    case 0:
                        HandleStatus0(a);
                        break;
                    default:
                        break;
                }
            }  
        }

В некоторых случаях (в HandleStatus1 и HandleStatus2) мне нужно перейти в БД, внести некоторые обновления, а затем снова заполнить коллекцию allItems, вызвав метод GetAllItems.

Этот тип кода вызывает исключение Stack.Overflow в WinFormsApp. У меня два вопроса:
1. Будет ли исключение такого типа генерироваться в приложении WinService с использованием того же кода?
2. Каково ваше мнение об использовании таймеров вместо метода самостоятельного вызова?

Это было полезно?

Решение

"Самовозвратный метод" более правильно называется " рекурсивный метод " . Ваше решение креативно, я дам вам это. Но не делай этого. Пространство стека очень ограничено. Вы увидите эту проблему при переходе на службу, и есть гораздо лучшие способы решения этой проблемы. Таймер очень подходит для использования в сервисе.

Другие советы

Рекурсивный вызов метода в вашем случае такой же плохой , как и использование таймера для этого. Вы не должны делать ни один из них!

Просто используйте простой цикл и отправьте поток в спящий режим на некоторое время.

MS IL имеет код операции .tail. Но c # dot хочет распознать хвостовую рекурсию (кстати, хвостовая рекурсия в .net такая медленная ((

Зачем вам вообще нужно проходить курс? Нет оператора управления потоком, который позволил бы методу прекратить рекурсию и выйти из цепочки. Бесконечные рекурсии, вероятно, являются причиной переполнения. Лучшее решение - полностью отказаться от рекурсии. Удаление оболочки обертки приводит к тому же результату без необходимости повторять:

private void MonitorItems()
{
    if(someCondition)
    {
        dateSelected = DateTime.Now;
        GetAllItems();
    }
    if(allItems.Count>0)
        CheckAllItems();
}

Это даст тот же результат без зацикливания. Затем вы можете реализовать правила для повторения вызова в контексте среды выполнения: нажатие кнопки на форме или таймер в приложении-службе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top