解决C#代码中的InvalidOperationException: Collection was modified问题

健身生活志 2022-04-05 ⋅ 62 阅读

在 C# 开发中,很多时候会遇到 InvalidOperationException: Collection was modified 这样的异常。这个异常通常发生在遍历或修改集合时,导致集合的状态被并发地修改。

本篇博客将探讨这个异常的原因,并提供一些解决方法来避免或处理这个问题。

异常原因

异常 "Collection was modified" 引发的原因通常是由于在迭代集合的同时修改了集合的结构。当一个线程正在迭代集合的元素时,另一个线程同时修改了集合,这将导致并发的修改操作,进而引发该异常。

以下是一个示例代码:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
    if (number % 2 == 0)
    {
        numbers.Remove(number); // 在迭代过程中移除元素
    }
}

上述代码在迭代 numbers 列表时尝试移除偶数。然而,由于在迭代过程中对集合进行了修改操作,将会抛出 "Collection was modified" 异常。

解决方法

为避免 InvalidOperationException: Collection was modified 异常的发生,我们可以采取以下几种解决方法:

  1. 使用 for 循环代替 foreach 循环:使用 for 循环可以避免在迭代过程中移除或添加元素的问题。在循环中可以通过索引来访问集合的元素,从而避免并发修改。

    List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    
    for (int i = 0; i < numbers.Count; i++)
    {
        if (numbers[i] % 2 == 0)
        {
            numbers.Remove(numbers[i]); // 在迭代过程中移除元素
            i--; // 由于移除了元素,需要减小索引以保持正确迭代
        }
    }
    
  2. 使用线程同步机制:可以使用线程同步机制,如互斥锁(Mutex)或信号量(Semaphore),在操作集合之前进行同步。这样可以确保在一个线程正在修改集合时,其他线程无法同时进行修改。

    List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    Mutex mutex = new Mutex();
    
    // 使用互斥锁同步操作
    mutex.WaitOne();
    
    // 在这里进行集合的修改操作
    
    mutex.ReleaseMutex();
    
  3. 创建临时副本:在操作集合之前,可以创建一个临时副本来避免并发修改的问题。通过在副本上进行操作,可以避免在迭代期间改变原始集合的内容。

    List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
    
    List<int> tempNumbers = new List<int>(numbers); // 创建副本
    
    foreach (int number in tempNumbers)
    {
        if (number % 2 == 0)
        {
            numbers.Remove(number);
        }
    }
    

这些解决方法可以根据具体情况进行选择和调整,以解决 InvalidOperationException: Collection was modified 异常的问题。

希望本篇博客能够帮助您解决 C# 代码中的并发修改集合引发的异常问题。如有疑问或其他相关问题,请随时留言讨论。


全部评论: 0

    我有话说: