我无法找到这个错误的根源,因为当附加调试器时,它似乎没有发生。

修改集合;枚举操作可能无法执行

下面是代码。

这是Windows服务中的WCF服务器。只要有数据事件,服务就会调用NotifySubscribers()方法(随机间隔,但不经常——大约每天800次)。

When a Windows Forms client subscribes, the subscriber ID is added to the subscribers dictionary, and when the client unsubscribes, it is deleted from the dictionary. The error happens when (or after) a client unsubscribes. It appears that the next time the NotifySubscribers() method is called, the foreach() loop fails with the error in the subject line. The method writes the error into the application log as shown in the code below. When a debugger is attached and a client unsubscribes, the code executes fine.

您认为这段代码有问题吗?我需要使字典线程安全吗?

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class SubscriptionServer : ISubscriptionServer
{
    private static IDictionary<Guid, Subscriber> subscribers;

    public SubscriptionServer()
    {            
        subscribers = new Dictionary<Guid, Subscriber>();
    }

    public void NotifySubscribers(DataRecord sr)
    {
        foreach(Subscriber s in subscribers.Values)
        {
            try
            {
                s.Callback.SignalData(sr);
            }
            catch (Exception e)
            {
                DCS.WriteToApplicationLog(e.Message, 
                  System.Diagnostics.EventLogEntryType.Error);

                UnsubscribeEvent(s.ClientId);
            }
        }
    }
    
    public Guid SubscribeEvent(string clientDescription)
    {
        Subscriber subscriber = new Subscriber();
        subscriber.Callback = OperationContext.Current.
                GetCallbackChannel<IDCSCallback>();

        subscribers.Add(subscriber.ClientId, subscriber);
        
        return subscriber.ClientId;
    }

    public void UnsubscribeEvent(Guid clientId)
    {
        try
        {
            subscribers.Remove(clientId);
        }
        catch(Exception e)
        {
            System.Diagnostics.Debug.WriteLine("Unsubscribe Error " + 
                    e.Message);
        }
    }
}

当前回答

好的,帮助我的是向后迭代。我试图从列表中删除一个条目,但向上迭代,它搞砸了循环,因为该条目不再存在了:

for (int x = myList.Count - 1; x > -1; x--)
{
    myList.RemoveAt(x);
}

其他回答

因此,解决这个问题的另一种方法是创建一个新的字典,而不是删除元素,只添加你不想删除的元素,然后用新的字典替换原来的字典。我不认为这是一个太大的效率问题,因为它不会增加你迭代结构的次数。

可以将订阅者字典对象复制到相同类型的临时字典对象,然后使用foreach循环迭代该临时字典对象。

InvalidOperationException - 发生了InvalidOperationException。它报告foreach循环中的“集合被修改”

使用break语句,一旦对象被移除。

ex:

ArrayList list = new ArrayList(); 

foreach (var item in list)
{
    if(condition)
    {
        list.remove(item);
        break;
    }
}

实际上,在我看来,问题似乎是您正在从列表中删除元素,并期望继续读取列表,就像什么都没有发生一样。

你真正需要做的是从头开始,再回到起点。即使您从列表中删除了元素,也可以继续读取它。

我见过很多这样的选择,但对我来说,这是最好的。

ListItemCollection collection = new ListItemCollection();
        foreach (ListItem item in ListBox1.Items)
        {
            if (item.Selected)
                collection.Add(item);
        }

然后简单地遍历集合。

注意,ListItemCollection可以包含重复项。默认情况下,没有任何东西阻止将副本添加到集合中。为了避免重复,你可以这样做:

ListItemCollection collection = new ListItemCollection();
            foreach (ListItem item in ListBox1.Items)
            {
                if (item.Selected && !collection.Contains(item))
                    collection.Add(item);
            }