一个在百度上都找不到答案的问题--集合在枚举数实例化后进行了修改

hongruixing 2011-01-24 10:15:41
年终公司开年会,节目上有个抽奖节目,公司要求用程序随机抽取中奖者,因为抽奖者众多,我用了多线程来进行开发,我的大概思路是这样的:主界面上有5列,每列有13个Label存放待抽奖者,每个线程控制一列,当按下开始按钮时,5个线程同时启动,每个线程通过如下方法为Label赋值:
if (Thread.CurrentThread.ManagedThreadId == t2.ManagedThreadId)
{

while (true)
{
int z = 0;
Random a = new Random();
for (int i = 14; i <= 2 * 13; i++)
{
z = a.Next(200, 400);
((Label)(panel2.Controls.Find("L" + i.ToString(), true)[0])).Text = GetStaff.arrStaff[z].ToString();
}

Thread.Sleep(100);
}
}
这样一旦启动线程,Label上的名字就实现变换,当按下停止按钮的时候,线程终止,Label上的Text就是中奖者,但问题来了,在启动一个线程的时候,这个做法没问题,但在5个线程一起开的时候,运行时会报一个异常:集合在枚举数实例化后进行了修改.这句话什么意思??异常那句就是((Label)(panel2.Controls.Find("L" + i.ToString(), true)[0])).Text = GetStaff.arrStaff[z].ToString();
其中GetStaff类是用来读取员工名单的一个txt文件,类代码如下class GetStaff
{
public static string[] GetStaffInfo()
{

string[] staff = File.ReadAllLines(@"StaffSources.txt",Encoding.Default);
return staff;
}

public static ArrayList arrStaff = new ArrayList(GetStaffInfo());
}
请问是什么原因导致异常?急求解决办法!谢谢
...全文
794 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
xxiju203 2011-01-24
  • 打赏
  • 举报
回复
似乎Find方法内部用的是foreach实现。
wuyq11 2011-01-24
  • 打赏
  • 举报
回复
控件或窗体.Invoke((EventHandler)delegate
{
//操作界面
});
也可使用BackGroundWorker
ThreadPool.QueueUserWorkItem
phil999 2011-01-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hongruixing 的回复:]

8楼的,你好,因为抽奖者名额多,用单一线程给65个Label赋值会很慢的,所以采用了多线程,一个线程控制13个label的变化
[/Quote]

所有对控件的操作最终都要在 UI 线程上完成,你用了多线程,就不得不测试 InvokeRequired 属性,然后使用 Invoke 来执行委托。动画效果本来就不是 winform 的长处。试试 DoubleBuffered。

yizhili 2011-01-24
  • 打赏
  • 举报
回复
考虑一下单线程吧
这样做最终还是在一个线程里处理的,还不如直接单线程

[Quote=引用 19 楼 hongruixing 的回复:]

用了12楼的方法虽然没有报错,但是UI显示不正常
[/Quote]
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
用了12楼的方法虽然没有报错,但是UI显示不正常
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
是的,怎么解决呢
yizhili 2011-01-24
  • 打赏
  • 举报
回复
这个是因为 UI 对象不能在创建它的线程(主线程)之外修改吧?
12 楼用 this.Invoke 正是把具体的处理又丢回 UI 线程了

[Quote=引用 11 楼 hongruixing 的回复:]

具体报错原因是:“panel2.Text”引发了“Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException”类型的异常
[/Quote]
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
是不是Invoke调用的位置不正确
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
额,是没有报错了,但是显示却有点问题,有些Label不能正常显示出名字!
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
好,我试试!
KissXYL 2011-01-24
  • 打赏
  • 举报
回复
所以了,问题描述清晰点吗。你按我说的,用一个数组缓存是对的。或是你Invoke一下。
this.Invoke((EventHandler)delegate
{
((Label)(panel2.Controls.Find("L" + i.ToString(), true)[0])).Text = GetStaff.arrStaff[z].ToString();
});
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
具体报错原因是:“panel2.Text”引发了“Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException”类型的异常
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
8楼的,你好,因为抽奖者名额多,用单一线程给65个Label赋值会很慢的,所以采用了多线程,一个线程控制13个label的变化
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
嗯,panel2.Controls在报错时里面居然有130个Label,但是我在panel2里面只放了65个,为什么会多了一倍呢???
phil999 2011-01-24
  • 打赏
  • 举报
回复
“抽奖者众多”并不是使用多线程的理由

((Label)(panel2.Controls.Find("L" + i.ToString(), true)[0])).Text = GetStaff.arrStaff[z].ToString();

这句拆开几句写,先搞清楚是哪个集合出了问题
KissXYL 2011-01-24
  • 打赏
  • 举报
回复
你看来没看懂我给你的回复,你点详细,贴出具体那一行出错。问题应该一目了然。
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
你好,5楼的仁兄,现在问题似乎不是在Find方法上,我觉得2楼的仁兄说得有点道理,但是我很纳闷,线程里面根本没有修改过arrStaff的值呢
KissXYL 2011-01-24
  • 打赏
  • 举报
回复
出问题时候,点详细,可以看到具体问题。
少用panel2.Controls.Find的方法,自己记录下来,例如
Label[] lbs = new Label[]{Label1,Label2 等};
使用这个lbs数组。
hongruixing 2011-01-24
  • 打赏
  • 举报
回复
1楼的,你看清楚,我没有用到foreach,不要在网上随便找一个回答复制粘贴,2楼的,我虽然有5个线程同时调用arrStaff,但是我并没有对她进行过修改啊!!
加载更多回复(4)

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧