C#chart运行一会会报”集合已修改;可能无法执行枚举操作。”错误,求教大神!!!

Leo·P 2019-05-09 01:05:12
private void timer1_Tick(object sender, EventArgs e)
{
//实时
Thread thread1 = new Thread(new ThreadStart(alone));
thread1.IsBackground = true;
thread1.Start();
}
private void PHT_Frm_FilmThickness_Load(object sender, EventArgs e)
{
double d = 0;
for (int i = 0; i < 50; i++)
{
d = d + 0.1;
S1[i] = 18 + d;
}
}

void alone()
{
Thread.Sleep(1000);
for (int i = 0; i <= 199; i++)
{
Random ra = new Random();
int r = ra.Next(0, 49);
Thread.Sleep(10);
d1[i] = S1[r];
}
//平均值AVG
label7.Text = "AVG=" + d1.Average().ToString();
//极差R
label6.Text = "R=" + (d1.Max() - d1.Min()).ToString();
//标准差
double sSum2 = 0;
for (int j = 0; j < d1.Length; j++)
{
sSum2 += (d1[j] - d1.Average()) * (d1[j] - d1.Average());
}
label5.Text = "S=" + Math.Sqrt((sSum2 / d1.Length)).ToString();

//清空chart2
for (int i = 0; i < chart2.Series.Count; i++)
{
chart2.Series[i].Points.Clear();
}

Series ss2 = new Series();
chart2.Series.Add(ss2);
ss2.ChartType = SeriesChartType.FastLine;
ChartArea chartArea2 = chart2.ChartAreas[0];
chartArea2.AxisX.Minimum = 0;
chartArea2.AxisX.Maximum = 200;
//chartArea2.AxisY.Minimum = 15;
//chartArea2.AxisY.Maximum = 25d;
chartArea2.AxisY.IsStartedFromZero = false;
//ss.BorderWidth = 2;
ss2.Color = System.Drawing.Color.Red;

for (int y = 0; y <= 199; y++)
{
//输出
ss2.Points.AddXY(y, d1[y]);
//膜厚SV
label8.Text = "SV=" + d1[y].ToString();
}
}
...全文
600 点赞 收藏 18
写回复
18 条回复
ZhuCheng Xie 2019年05月22日
我比较好奇,你在timer里,为何还要开一个线程组做这个事。 如果你使用的是winform的timer。那么去掉线程,直接alone(), 应该就没这个问题了。 因为winform的timer,第二次启动会等第一次完成后才开始。 这也是被很多人吐槽说timer不精准的原因。
回复 点赞
Leo·P 2019年05月10日
引用 13 楼 stherix 的回复:
[quote=引用 12 楼 TY_Peng 的回复:] [quote=引用 9 楼 stherix 的回复:] [quote=引用 8 楼 TY_Peng 的回复:] 我试了单用timer不会报错,单用线程和timer线程一起的都会报错,但单用timer程序会变得非常卡,有什么能解决的吗?
你可以直接起单个线程、Task 然后在里面循环,用Sleep还是Task.Wait都随你意了[/quote] 这样不行,还是会报错[/quote] 因为会跨线程操作界面 所以更新chart的时候要用Invoke[/quote] 解决了,感谢大佬
回复 点赞
诗和远方C 2019年05月10日
引用 5 楼 xian_wwq 的回复:
foreach的过程中是不能进行增、删处理的。
应用场景没有说明,
timer1_Tick感觉是timer控件的处理函数,为何在timer中起用线程呢?

timer有个致命的问题
一旦本轮次处理超时或者异常没有处理完成,
下一轮时间到了仍然会执行
而函数处理如果不支持重入,
那么就会引发奇奇怪怪的问题



老哥,你跟3L说的不一样,我试了一下,timer本轮处理超时,会等到超时任务完成下一次定时器任务开启动,本轮处理异常,会在本轮抛异常。

回复 点赞
诗和远方C 2019年05月10日
引用 3 楼 正怒月神 的回复:
我比较好奇,你在timer里,为何还要开一个线程组做这个事。
如果你使用的是winform的timer。那么去掉线程,直接alone(),
应该就没这个问题了。
因为winform的timer,第二次启动会等第一次完成后才开始。
这也是被很多人吐槽说timer不精准的原因。

老哥说对了,5L老哥说错了
回复 点赞
ZENG~ 2019年05月10日
用线程就行不要再外层加个定时器
回复 点赞
stherix 2019年05月09日
引用 12 楼 TY_Peng 的回复:
[quote=引用 9 楼 stherix 的回复:] [quote=引用 8 楼 TY_Peng 的回复:] 我试了单用timer不会报错,单用线程和timer线程一起的都会报错,但单用timer程序会变得非常卡,有什么能解决的吗?
你可以直接起单个线程、Task 然后在里面循环,用Sleep还是Task.Wait都随你意了[/quote] 这样不行,还是会报错[/quote] 因为会跨线程操作界面 所以更新chart的时候要用Invoke
回复 点赞
Leo·P 2019年05月09日
引用 9 楼 stherix 的回复:
[quote=引用 8 楼 TY_Peng 的回复:] 我试了单用timer不会报错,单用线程和timer线程一起的都会报错,但单用timer程序会变得非常卡,有什么能解决的吗?
你可以直接起单个线程、Task 然后在里面循环,用Sleep还是Task.Wait都随你意了[/quote] 这样不行,还是会报错
回复 点赞
wangmoxhn 2019年05月09日
简单,修改和枚举s的时候,lock住s
回复 点赞
wangmoxhn 2019年05月09日
简单,修改和枚举s的时候,lock住s
回复 点赞
stherix 2019年05月09日
引用 8 楼 TY_Peng 的回复:
我试了单用timer不会报错,单用线程和timer线程一起的都会报错,但单用timer程序会变得非常卡,有什么能解决的吗?
你可以直接起单个线程、Task 然后在里面循环,用Sleep还是Task.Wait都随你意了
回复 点赞
Leo·P 2019年05月09日
我试了单用timer不会报错,单用线程和timer线程一起的都会报错,但单用timer程序会变得非常卡,有什么能解决的吗?
回复 点赞
Leo·P 2019年05月09日
不加timer也还是会发生这个错误的
回复 点赞
物联网_咸鱼 2019年05月09日
用线程就行不要再外层加个定时器
回复 点赞
xian_wwq 2019年05月09日
foreach的过程中是不能进行增、删处理的。
应用场景没有说明,
timer1_Tick感觉是timer控件的处理函数,为何在timer中起用线程呢?

timer有个致命的问题
一旦本轮次处理超时或者异常没有处理完成,
下一轮时间到了仍然会执行
而函数处理如果不支持重入,
那么就会引发奇奇怪怪的问题

回复 点赞
stherix 2019年05月09日
为什么要在timer_Tick里又起线程? 直接alone()就行了 否则可能存在多个alone同时运行 这时候你修改了d1的值 而Average,Sum等方法都是基于枚举器的,在枚举器进行枚举的时候,集合被修改就会报这个错误
回复 点赞
正怒月神 2019年05月09日
我比较好奇,你在timer里,为何还要开一个线程组做这个事。 如果你使用的是winform的timer。那么去掉线程,直接alone(), 应该就没这个问题了。 因为winform的timer,第二次启动会等第一次完成后才开始。 这也是被很多人吐槽说timer不精准的原因。
回复 点赞
正怒月神 2019年05月09日
简单来说, 就是你在for操作char集合的时候,外部有其他操作修改了char集合。 因为你有一个定时器。然后chart2.Series.Add(ss2);修改了集合长度。
回复 点赞
OrdinaryCoder 2019年05月09日
有可能是你线程启动的时候chart正在初始化或者是其他的操作 尝试一下延时启动线程 或者在表格初始化结束之后启动线程
回复 点赞
发动态
发帖子
C#
创建于2007-09-28

8.5w+

社区成员

64.0w+

社区内容

.NET技术 C#
社区公告
暂无公告