Ошибка Stack.Overflow - приложение WinForms WinService - PullRequest
0 голосов
/ 27 октября 2009

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

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

Метод GetAllItems отправляется в БД и получает все новые элементы для коллекции -> allItems. Затем метод 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. Каково ваше мнение об использовании таймеров вместо метода самостоятельного вызова?

Ответы [ 4 ]

1 голос
/ 27 октября 2009

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

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

1 голос
/ 27 октября 2009

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

0 голосов
/ 27 октября 2009

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

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

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

0 голосов
/ 27 октября 2009

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

...