System.invalidoperationexception:'集合被修改;枚举操作可能无法执行。 [英] System.invalidoperationexception: 'collection was modified; enumeration operation may not execute.'

查看:92
本文介绍了System.invalidoperationexception:'集合被修改;枚举操作可能无法执行。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



我尝试开发一个与HID设备通信的应用程序我收到System.InvalidOperationException:'收集被修改;枚举操作可能无法执行。'错误。



我尝试过:



Hello everyone,

I try to develop an application that communicate with HID device I got System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.' error.

What I have tried:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CyUSB;
using System.Threading;

namespace EGI
{
    public partial class EGI_Main : Form
    {
        // *********************** START OF PROGRAM MAIN ****************************** //

        USBDeviceList usbDevices = null;            // Pointer to list of USB devices
        CyHidDevice myHidDevice = null;             // Handle of USB device

        int VID = 0x04B4;                           // Cypress Vendor ID
        int PID = 0xE177;                           // Example Project Product ID

        bool communicate = false;                   // Communication status

        byte que = 00;                              // Command Byte
        byte PGAValue = 02;                         // PGA
        byte[] receivedDatas = new byte[128];       // Byte array to store 128 bytes of received data from device

        /**********************************************************************
        * NAME: EGI - Ekin Generic HID Communication Interface
        *
        * DESCRIPTION: Main function called initially upon the starting of the
        * application. Used to un-initialized variables, the GUI application, register
        * the event handlers, and check for a connected device.
        *
        ***********************************************************************/

        public EGI_Main()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            // Create a list of CYUSB devices for this application
            usbDevices = new USBDeviceList(CyConst.DEVICES_HID);
            //Add event handlers for device attachment and device removal
            usbDevices.DeviceAttached += new EventHandler(usbDevices_DeviceAttached);
            usbDevices.DeviceRemoved += new EventHandler(usbDevices_DeviceRemoved);
            //Connect to the USB device
            GetDevice();
        }

        /**********************************************************************
        * NAME: EGI_Main_Load
        *
        * DESCRIPTION: Loads and sets necessary companents and settings on start.
        *
        ***********************************************************************/

        private void EGI_Main_Load(object sender, EventArgs e)
        {
            // Real data graph settings
            chartResult.ChartAreas[0].AxisX.ScaleView.Zoom(0, 127);
            chartResult.ChartAreas[0].AxisY.ScaleView.Zoom(0, 255);
            chartResult.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            chartResult.Series[0].Color = Color.Black;
            chartResult.Series[0].BorderWidth = 3;

            // On line average result graph settings
            chartResult.Series.Add("onLineAvg");
            chartResult.Series["onLineAvg"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            chartResult.Series["onLineAvg"].Color = Color.Red;
            chartResult.Series["onLineAvg"].BorderWidth = 3;

            // Multipline with on line average result graph settings
            chartResult.Series.Add("multOnLineAvg");
            chartResult.Series["multOnLineAvg"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            chartResult.Series["multOnLineAvg"].Color = Color.Navy;
            chartResult.Series["multOnLineAvg"].BorderWidth = 3;

            // Exceed point(s) graph settings
            chartResult.Series.Add("exceed");
            chartResult.Series["exceed"].Color = Color.Brown;
            chartResult.Series["exceed"].BorderWidth = 3;

            for(int i = 0; i < 128; i++)
            {
                chartResult.Series[0].Points.AddXY(i, 0);
                chartResult.Series["onLineAvg"].Points.AddXY(i, 0);
                chartResult.Series["multOnLineAvg"].Points.AddXY(i, 0);
            }
        }

        /**********************************************************************
        * NAME: usbDevices_DeviceRemoved
        *
        * DESCRIPTION: Event handler for the removal of a USB device. When the removal
        * of a USB device is detected, this function will be called which will check to
        * see if the device removed was the device we were using. If so, then reset
        * device handler (myHidDevice), disable the timer, and update the GUI.
        *
        ***********************************************************************/

        public void usbDevices_DeviceRemoved(object sender, EventArgs e)
        {
            USBEventArgs usbEvent = e as USBEventArgs;
            if ((usbEvent.ProductID == PID) && (usbEvent.VendorID == VID))
            {
                InputTimer.Enabled = false; // Disable interrupts for polling HID
                myHidDevice = null;
                GetDevice(); // Process device status
            }
        }

        /**********************************************************************
        * NAME: usbDevices_DeviceAttached
        *
        * DESCRIPTION: Event handler for the attachment of a USB device. The function
        * first checks to see if a matching device is already connected by seeing
        * if the handler (myHidDevice) is null. If no device is previously attached,
        * the function will call GetDevice to check and see if a matching device was
        * attached.
        *
        ***********************************************************************/

        public void usbDevices_DeviceAttached(object sender, EventArgs e)
        {
            if (myHidDevice == null)
            {
                GetDevice(); // Process device status
            }
        }

        /**********************************************************************
        * NAME: GetDevice
        *
        * DESCRIPTION: Function checks to see if a matching USB device is attached
        * based on the VID and PID provided in the application. When a device is
        * found, it is assigned a handler (myHidDevice) and the GUI is updated to
        * reflect the connection. Additionally, if the device is not connected,
        * the function will update the GUI to reflect the disconnection.
        *
        ***********************************************************************/
        public void GetDevice()
        {
            //Look for device matching VID/PID
            myHidDevice = usbDevices[VID, PID] as CyHidDevice;
            if (myHidDevice != null) //Check to see if device is already connected
            {
                Status.Text = "Connected";
                Status.ForeColor = Color.Green;
                InputTimer.Enabled = true; //Enable background timer
            }
            else
            {
                Status.Text = "Disconnected";
                Status.ForeColor = Color.Red;
            }
        }
        
        /**********************************************************************
        * NAME: Set_VidPid_Click
        *
        * DESCRIPTION: Updates the applications Vendor ID and Product ID based on
        * user input when the "Set" button is clicked. This will cause the default VID
        * and PID of 0x04B4 and 0xE177 to be overwritten. The function will then
        * call GetDevice() to check for matching USB device.
        *
        ***********************************************************************/
        private void Set_VidPid_Click(object sender, EventArgs e)
        {
            //Respond to update of VID and PID value by pressing the "Set" button
            VID = Convert.ToInt32(VidTextBox.Text, 16);
            PID = Convert.ToInt32(PidTextBox.Text, 16);
            GetDevice();
        }

        /**********************************************************************
        * NAME: receive_Click
        *
        * DESCRIPTION: Starts and stops communication with device.
        *
        ***********************************************************************/

        private void receive_Click(object sender, EventArgs e)
        {
            if (communicate)
            {
                communicate = false;
                receive.Text = "Communicate";
                receive.BackColor = Color.White;
                receive.ForeColor = Color.Black;
            }
            else
            {
                communicate = true;
                receive.Text = "Stop";
                receive.BackColor = Color.Red;
                receive.ForeColor = Color.White;
                que = 00;
                backgroundWorkerGetAndProcessData.RunWorkerAsync();
            }
        }

        /**********************************************************************
        * NAME: communicateNow
        *
        * DESCRIPTION:Sends commands to device.
        *
        ***********************************************************************/

        private void communicateNow()
        {
            if (communicate)
            {
                // Load data into Output Buffer
                myHidDevice.Outputs.DataBuf[0] = 00;                                    // Report ID
                myHidDevice.Outputs.DataBuf[1] = (byte)numericUpDownThreshold.Value;    // Threshold
                myHidDevice.Outputs.DataBuf[2] = (byte)numericUpDownPB.Value;           // PB
                myHidDevice.Outputs.DataBuf[3] = PGAValue;                              // PGA
                myHidDevice.Outputs.DataBuf[4] = 87;                                    // W/R
                myHidDevice.Outputs.DataBuf[5] = que;                                   // Command byte
                myHidDevice.Outputs.DataBuf[6] = 00;
                myHidDevice.Outputs.DataBuf[7] = 00;
                myHidDevice.Outputs.DataBuf[8] = 00;
                myHidDevice.Outputs.DataBuf[9] = 00;

                // Function call to send data to device
                myHidDevice.WriteOutput();
                // Function call to receive data from device
                myHidDevice.ReadInput();

                byte[] tempData = myHidDevice.Inputs.DataBuf;

                for (int i = 2; i < myHidDevice.Inputs.DataBuf.Length - 1; i++)
                {
                    if (que == 0)
                        receivedDatas[i - 2] = tempData[i];
                    else if (que == 1)
                        receivedDatas[32 + i - 2] = tempData[i];
                    else if (que == 2)
                        receivedDatas[64 + i - 2] = tempData[i];
                    else if (que == 3)
                        receivedDatas[96 + i - 2] = tempData[i];
                }

                if (que < 03)
                {
                    que++;
                    communicateNow();
                }
                else
                {
                    que = 00;
                }
            }
        }
        

        /**********************************************************************
        * NAME: dataProcess
        *
        * DESCRIPTION: Regroup the datas, writes them to specific textboxes and
        * calls calculateAndDrawGraph to calculate and draw graph.
        *
        ***********************************************************************/

        private void dataProcess()
        {
            byte[] realDatas = receivedDatas;
            bool highLightPower = false;
            bool lowLightPower = false;

            // Clear textboxes
            receivedData_00.Text = null;
            receivedData_01.Text = null;
            receivedData_02.Text = null;
            receivedData_03.Text = null;

            // Count datas to separate to textboxes
            int countOfDatas = 0;

            // Write all datas to specified textboxes
            for(int i = 0; i < realDatas.Length; i++)
            {
                if (countOfDatas < 32)
                    receivedData_00.AppendText(realDatas[i] + " - ");
                else if (countOfDatas < 64)
                    receivedData_01.AppendText(realDatas[i] + " - ");
                else if (countOfDatas < 96)
                    receivedData_02.AppendText(realDatas[i] + " - ");
                else if (countOfDatas < 128)
                    receivedData_03.AppendText(realDatas[i] + " - ");

                // Check whether light power is high or low.
                if (realDatas[i] >= 190)
                    highLightPower = true;
                else if (realDatas[i] <= 25)
                    lowLightPower = true;

                countOfDatas++;
            }

            if (highLightPower)
            {
                labelLightPower.BackColor = Color.Red;
                labelLightPower.ForeColor = Color.White;
                labelLightPower.Text = "Decrease";
            }
            else if (lowLightPower)
            {
                labelLightPower.BackColor = Color.Yellow;
                labelLightPower.ForeColor = Color.Black;
                labelLightPower.Text = "Increase";
            }
            else
            {
                labelLightPower.BackColor = Color.Green;
                labelLightPower.ForeColor = Color.White;
                labelLightPower.Text = "";
            }

        }

        /**********************************************************************
        * NAME: calculateAndDrawGraph
        *
        * DESCRIPTION: Calculates averages and draws their graphs. Recall 
        * communicateNow() to receive new datas.
        *
        ***********************************************************************/

        private void calculateAndDrawGraph()
        {
            byte[] realDatas = receivedDatas;
            byte[] onLineAvg = new byte[128];
            int[] multOnLineAvg = new int[128];
            /* some codes */

            Thread.Sleep(900);
        }

        /**********************************************************************
        * NAME: radioButton_CheckedChanged
        *
        * DESCRIPTION: Sets PGAValue.
        *
        ***********************************************************************/

        private void radioButton_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton1.Checked)
                PGAValue = 01;
            else if (radioButton2.Checked)
                PGAValue = 02;
            else if (radioButton4.Checked)
                PGAValue = 04;
            else if (radioButton8.Checked)
                PGAValue = 08;
        }

        /**********************************************************************
        * NAME: backgroundWorkerGetAndProcessData_DoWork
        *
        * DESCRIPTION: Starts background worker to get data and process them.
        *
        ***********************************************************************/

        private void backgroundWorkerGetAndProcessData_DoWork(object sender, DoWorkEventArgs e)
        {
            communicateNow();
            dataProcess();
            calculateAndDrawGraph();
        }

        /**********************************************************************
        * NAME: backgroundWorkerGetAndProcessData_RunWorkerCompleted
        *
        * DESCRIPTION: Recalls background worker to get data and process them.
        *
        ***********************************************************************/

        private void backgroundWorkerGetAndProcessData_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            backgroundWorkerGetAndProcessData.RunWorkerAsync();
        }
    }
}

推荐答案

看看这里:枚举在C#中更改的集合Magnus Montin [ ^ ]



简而言之:无论何时修改循环内的集合,您都会看到这样的消息。请阅读参考文章。

我建议使用调试器找出发生此错误的位置。



另外的资源:

如何处理此错误:收集被修改;枚举操作可能无法执行。 [ ^ ]

集合已被修改;枚举操作可能无法执行。错误 [ ^ ]
Have a look here: Enumerating collections that change in C# | Magnus Montin[^]

In a few words: whenever you modify a collection inside a loop, you'll see such of message. Please, read referenced article.
I'd suggest to use debugger to find out where this error occurs.

Another resources:
How to handle this error: Collection was modified; enumeration operation may not execute.[^]
"Collection was modified; enumeration operation may not execute." error[^]


正如我在上一个问题上所说: Program stucks when read data from HID C#[< a href=\"https://www.codeproject.com/Questions/1223724/Program-stucks-when-read-data-from-HID-Csharp\" target=\"_blank\" title=\"New Window\">^]



As I said on your previous question: Program stucks when read data from HID C#[^]

Quote:

That's why I said it needs a complete redesign: you can't access UI controls from any thread other than the UI thread, and the standard .NET controls aren;t thread safe. You can’t just throw all the code into a different thread and hope it works, you need to think about what needs to be done in which thread and how the two threads need to communicate with each other, and when.

That's why I said it needs a complete redesign: you can't access UI controls from any thread other than the UI thread, and the standard .NET controls aren;t thread safe. You can't just throw all the code into a different thread and hope it works, you need to think about what needs to be done in which thread and how the two threads need to communicate with each other, and when.


I just delete my functions and move their codes inside
I just delete my functions and move their codes inside
backgroundWorkerGetAndProcessData_RunWorkerCompleted

functions. Now there is no problem.

functions. Now there is no problem.


这篇关于System.invalidoperationexception:'集合被修改;枚举操作可能无法执行。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆