集合在foreach循环中被修改

时间:2017-11-14 15:53:37

标签: android xamarin

我试图从蓝牙设备发送记录的通知,并定期更新UI以显示记录。下面的while循环位于自己的线程中以处理UI更新,而模块的其余部分负责其他任务。 gattCallbackBluetoothGattCallback类的一个实例,它添加到已接收记录的列表中,并在调用getHistory()时返回该列表。

我的问题是当我点击foreach行时,经过这么多次迭代后我得到一个错误:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

据我所知,history未在此处或我的代码中的任何其他地方进行更新,因此我对此错误感到困惑。我专门通过getHistory()检索记录历史记录的副本,以避免在foreach期间对其进行修改。任何人都可以建议可能导致它的原因或任何提示吗?

自从从Android 6.0.1上的Moto G Play切换到Android 7.1.1上的Moto E4后,这可能会引起问题。

        // Periodically check to see what needs updating
        while (!finishedDisplayThread)
        {
            // See if there are any new records to display
            int count;

            List<Record> history = gattCallback.getHistory();

            if (history == null)
            {
                count = 0;
            }
            else
            {
                count = history.Count;
            }

            // Only update the display if it has changed
            if(count != prevCount)
            {
                prevCount = count;
                List<string> recordList = new List<string>();
                if (history == null)
                {
                    recordList = new List<string>();
                    recordList.Add("No history.");
                }
                else
                {
                    foreach (Record record in history)
                    {
                        recordList.Add(record.ToRow());
                    }
                }

                //Update the display
                RunOnUiThread(() =>
                {
                    ListAdapter = new ArrayAdapter<string>(this, 
                                                           Resource.Layout.ListItemLayout, 
                                                           recordList);
                    recordCountText.Text = "" + count;
                });
            }

            Thread.Sleep(100);
        }

1 个答案:

答案 0 :(得分:2)

  

我通过getHistory()专门检索记录历史记录的副本,以避免在foreach期间对其进行修改。

您确定要获得副本吗?想象一下这个实现:

public List<Record> getHistory() {
    return history;
}

这将返回history的副本,但直接引用history本身。如果两个不同的位置调用此方法,则对其中一个返回值的任何更改都将影响另一个返回值。

如果你想要一份副本,你必须做这样的事情:

public List<Record> getHistory() {
    return new ArrayList<>(history);
}