erro Stack.Overflow - WinForms App Vs. WinService
-
06-07-2019 - |
Pergunta
Eu tenho um exemplo de código pequeno:
private void MonitorItems()
{
if (someCondition)
{
dateSelected = DateTime.Now;
GetAllItems();
}
else
{
if(allItems.Count>0)
CheckAllItems();
}
MonitorItems();
}
O Método getTodosOsItens vai para DB e obter todos os novos itens para a coleção -> allItems. Em seguida, o método 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;
}
}
}
Em alguns casos (em HandleStatus1 e HandleStatus2) eu preciso para ir para a DB, fazer algumas atualizações, e depois novamente preencher os allItems coleção com chamando os getTodosOsItens método.
Este tipo de código é lançando exceção Stack.Overflow em WinFormsApp.
Eu tenho duas perguntas:
1. É este tipo de exceção será lançada na aplicação WinService, usando o mesmo código?
2. Qual é a sua opinião de utilizar timers em vez do método de auto-chamando?
Solução
A "método de auto-chamando" é mais corretamente chamado de um "método recursivo" . Sua solução é criativo, eu vou te dar isso. Mas não fazê-lo. espaço de pilha é muito limitado. Você vai ver esse problema quando você mover para um serviço, e há muito melhores maneiras de lidar com isso. Um timer é muito apropriado quando usado em um serviço.
Outras dicas
recursiva chamar o método no seu caso é como mau como a utilização de um temporizador para fazê-lo. Você deve fazer nem !!
Basta usar um loop simples e enviar a dormir fio por algum tempo no meio.
MS IL tem .tail código op. Mas c # dot querem reconhecer cauda recursão (. Aliás, cauda recursão é tão lento em .net ((
Por que você precisa para recurse em tudo? Não existe o comando de controle de fluxo que permitirá que o método para parar de recursão e sair da cadeia. Os recursions infinitas é provavelmente o que está causando o transbordamento. Uma solução melhor seria acabar com a recursão completamente. Remover o invólucro outra realiza o mesmo resultado sem ter que recurse:
private void MonitorItems()
{
if(someCondition)
{
dateSelected = DateTime.Now;
GetAllItems();
}
if(allItems.Count>0)
CheckAllItems();
}
Este irá realizar o mesmo resultado sem ficar preso em um loop. Então você pode implementar regras para repetir a chamada no contexto do ambiente de execução:. Um clique de botão em um formulário ou um temporizador em um aplicativo de serviço