You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何定位C#异常对应的代码行与方法?新手求助

排查枚举集合时修改导致异常的思路(无直接foreach场景)

别慌,这种情况真的很常见,尤其是刚接触这类问题的时候!你说自己的ProcessActiveSilentNotific...方法里没有写foreach循环,但触发了枚举集合时修改集合的异常,其实问题不一定出在你直接写的循环里,下面给你几个排查方向:

  • 检查间接的枚举调用:很多你以为不是foreach的操作,内部其实会遍历集合。比如:

    • LINQ方法(WhereSelectAnyToList这些)都会枚举集合;
    • 集合的ForEach()扩展方法;
    • 甚至某些框架方法(比如绑定UI控件时的数据源遍历);
      你可以检查自己的方法里有没有调用这些操作,同时在过程中修改了集合(比如在Where过滤的同时给集合加元素)。
  • 警惕多线程冲突:如果你的集合是被多个线程共享的,哪怕你的方法里没有遍历,另一个线程可能正在枚举它,而你的方法在修改集合,这样也会触发异常。比如:

    • 你的ProcessActiveSilentNotific...可能在后台处理集合,同时UI线程或者定时器线程在往集合里加数据;
    • 这种情况可以试试用线程安全的集合(比如ConcurrentQueueConcurrentBag),或者在访问集合的地方加锁(lock语句)保护。
  • 深挖堆栈跟踪的调用链:异常的堆栈跟踪不是只看你自己的方法,要找抛出异常的那个底层方法(比如System.Collections.Generic.List<T>.Enumerator.MoveNext()),然后往上看调用链,找到第一个属于你代码的方法——那个方法里大概率有枚举集合的操作,哪怕不是你直接写的foreach

给你几个具体的排查小技巧:

  1. 把完整的堆栈跟踪(包括所有方法行)整理出来,顺着调用链往上找,定位到离异常最近的你的代码;
  2. 在你方法里所有修改集合的地方(Add/Remove/Clear)加个断点,触发异常时看看此时有没有其他线程正在遍历这个集合;
  3. 暂时把集合改成线程安全的版本,看看异常会不会消失——如果消失了,那基本就是多线程的问题。

内容的提问来源于stack exchange,提问作者Glenn

火山引擎 最新活动