I have following code for drawing a chart, from data that is read from a csv file. The data is generated from a C# windows service and added to the file every 35ms. In my code I am reading the file every second and updating my chart with the new accumulated data from the file. That means every time I read the file, I read more data then the last time. So I am generating something like a live chart that is updating every second.
When I read the data once, when all the data is generated, from the file, then my chart is working fine. But when I read every second the collected data from the file and throw it to my list, then I get immediatly the exception "Collection was modified; enumeration operation may not execute".
In all the entries about this problem, it is suggested to add a .ToList() to the for each operation. I have done this, but still getting the problem.
public Form1()
{
InitializeComponent();
this.Load = Form1_Load;
}
System.Timers.Timer timer_Chart_update = new System.Timers.Timer();
private void Form1_Load(object sender, EventArgs e)
{
this.Controls.Add(chart2);
Init_Chart_Update_Timer();
}
public static List<double> List_Position = new List<double>();
public static List<double> List_Current = new List<double>();
public static List<double> List_X_Axis = new List<double>();
public void Init_Chart_Update_Timer()
{
timer_Chart_update.Elapsed = new ElapsedEventHandler(OnTimedEvent);
timer_Chart_update.Interval = 1000;
timer_Chart_update.Start();
}
private void OnTimedEvent(object sender, EventArgs e)
{
Read_Test_File();
Draw_Chart();
}
public void Read_Test_File()
{
List_Position.Clear();
try
{
using (var fs = new FileStream("D:\\ConCheetah\\Test4\\test_files\\test_01.csv", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var streamReader = new StreamReader(fs, Encoding.UTF8, true))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
if (line == "$")
{
break;
}
bool isLetter = !String.IsNullOrEmpty(line) && Char.IsLetter(line[0]);
if (isLetter == true)
{
continue;
}
List_Position.Add(double.Parse(line));
}
}
}
catch(Exception e)
{
using (var writer = new StreamWriter(@"D:\ConCheetah\test4\log6.txt", true))
{
writer.WriteLine("File Read Error " e " " DateTime.Now.ToString());
}
}
}
public void Draw_Chart()
{
chart2.Series.Clear();
chart2.Titles.Clear();
chart2.Legends.Clear();
var newSeries_1 = new Series();
var newSeries_2 = new Series();
newSeries_1.ChartType = SeriesChartType.Line;
newSeries_2.ChartType = SeriesChartType.Line;
chart2.Series.Add(newSeries_1);
chart2.Series.Add(newSeries_2);
List_X_Axis.Clear();
for (int w = 0; w <= 940; w )
{
List_X_Axis.Add(w);
}
var t = chart2.Titles.Add("Title1");
t.Text = " Position/Current";
t.ForeColor = Color.Silver;
chart2.ChartAreas[0].AxisX.Title = ".";
chart2.ChartAreas[0].AxisY.Title = "mm";
chart2.ChartAreas[0].AxisY.TitleForeColor = Color.Orange;
chart2.ChartAreas[0].AxisY.LabelStyle.ForeColor = Color.Orange;
chart2.ChartAreas[0].AxisX.Minimum = 0d;
chart2.Series[0].Color = Color.Orange;
chart2.ChartAreas[0].AxisY.Minimum = 0;
chart2.ChartAreas[0].AxisY.Maximum = 15;
chart2.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart2.ChartAreas[0].AxisY2.Minimum = -350;
chart2.ChartAreas[0].AxisY2.Maximum = 350;
chart2.ChartAreas[0].AxisY2.Title = "% of Max. Current";
chart2.ChartAreas[0].AxisY2.TitleForeColor = Color.Yellow;
chart2.ChartAreas[0].AxisY2.LabelStyle.ForeColor = Color.Yellow;
chart2.ChartAreas[0].AxisY2.MajorGrid.LineColor = Color.Silver;
chart2.ChartAreas[0].AxisY2.MajorTickMark.LineColor = Color.Silver;
chart2.Series[1].YAxisType = AxisType.Secondary;
chart2.Series[1].Color = Color.Yellow;
chart2.ChartAreas[0].BackColor = Color.Black;
int x = 1;
foreach (float v in List_Position.ToList())
{
newSeries_1.Points.AddXY(x, v);
x ;
}
int x2 = 1;
foreach (float v in List_Position.ToList())
{
newSeries_2.Points.AddXY(x2, v);
x2 ;
}
}
Update_1
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Collections.Generic.List
1.Enumerator.MoveNext()
at System.Windows.Forms.DataVisualization.Charting.Series.ResetAutoValues(Boolean reset)
at System.Windows.Forms.DataVisualization.Charting.Series.UnPrepareData(ISite controlSite)
at System.Windows.Forms.DataVisualization.Charting.Data.DataManager.ChartPicture_AfterPaint(Object sender, ChartPaintEventArgs e)
at System.Windows.Forms.DataVisualization.Charting.ChartPicture.OnAfterPaint(ChartPaintEventArgs e)
CodePudding user response:
As Ralf has explained in the comment above the problem was that I used the chart control in the timer thread. So my timer was not synchronised with my form (main thread) and I got this error. I updated my timer initialisation as following, and it worked.
public void Init_Chart_Update_Timer()
{
timer_Chart_update.SynchronizingObject = this;
timer_Chart_update.Elapsed = new ElapsedEventHandler(OnTimedEvent);
timer_Chart_update.Interval = 1000;
timer_Chart_update.Start();
}