C#处理37999条报表数据时抛出System.StackOverflowException求助
问题根因
你遇到的System.StackOverflowException核心原因是RetornaListaFilmes方法采用了递归调用的方式处理数据:
- 每次循环处理完1条对应标题的记录后,只要
dados列表不为空,就会直接调用return RetornaListaFilmes(dados, filmes, boolOnePaises)触发递归 - 你有37999条数据,最坏情况下递归深度会达到数万级,远远超过.NET默认的1万左右的线程栈大小,直接触发栈溢出。
修复方案
1. 把递归逻辑改成迭代循环
直接把递归调用的逻辑替换成外层循环遍历dados列表,不需要每次调用方法本身,完全规避栈溢出风险,示例修改思路:
把原来的逻辑
foreach (var item in dados) { // 处理单条记录逻辑 dados.RemoveAll(x => x.titulo_original == item.titulo_original); if (dados.Count != 0) { return RetornaListaFilmes(dados, filmes, boolOnePaises); } else { break; } }
替换为外层循环,直到dados为空:
while(dados.Count > 0) { var item = dados[0]; // 原来的单条记录处理逻辑保持不变 dados.RemoveAll(x => x.titulo_original == item.titulo_original); }
2. 额外性能优化点
你当前代码还有大量冗余判断和重复遍历逻辑,处理3万条数据效率很低,可以同步优化:
- 所有
filme.GroupRightCountries.Where(x => x.Direito == dadosDireito[i].direito).ToList().Count == 0的判断,可以改用Any()方法,不需要生成新列表,写法为!filme.GroupRightCountries.Any(x => x.Direito == dadosDireito[i].direito) - 同一个
dadosDireito列表的重复遍历可以提前用GroupBy(x => x.direito)分组,不用每次循环都遍历整个列表查对应权限的国家 - 可以提前对原始
dados列表按titulo_original分组,不用每次处理完都调用RemoveAll删除元素,减少列表修改的性能开销
3. 异常处理修正
你当前代码的catch块写throw e;会清空原始异常的调用栈,不利于后续排查问题,直接改成throw;即可。
内容的提问来源于stack exchange,提问作者peterson benhame
相关产品推荐
相关产品推荐

