本文介绍了System.invalidoperationexception:'集合被修改;枚举操作可能无法执行。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 大家好, 我尝试开发一个与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(); } }}推荐答案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.backgroundWorkerGetAndProcessData_RunWorkerCompleted functions. Now there is no problem. functions. Now there is no problem. 这篇关于System.invalidoperationexception:'集合被修改;枚举操作可能无法执行。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-03 21:45
查看更多