闲着没事想起来用winform做一个随机的抽号程序,咋看来这么个东西其实并不难,不过对于一个菜鸟来说其实并不简单!尤其是对于多线程不是特别熟悉的新手来说。
首先,界面比较简单winform,(图片上传好麻烦~~!)
既然是随机抽取号码,就得有随机数(其实关键不在这里,图省事就random了)
可是在用到多线程的时候问题就出现了:
无法跨线程访问label控件,无法修改label的text。
网上找了很多资料,感觉例子搞得难以理解,遂自己撸起。。。。
1.有人这么写:
// Control.CheckForIllegalCrossThreadCalls = false;
//Label.CheckForIllegalCrossThreadCalls = false;
个人感觉这么干绝逼不合适,遂放弃!(原因有很多)
2.参考资料-用委托:
试着用委托的方式去解决,可无奈不知为何,使用了委托之后随机数字没有了滚动,最后直接界面卡死,(似乎没什么效果╮(╯-╰)╭)
3.使用invok调事件传方法。如代码所示
11 12 namespace 抽奖程序 13 { 14 public partial class Form1 : Form 15 { 16 17 18 public Form1() 19 { 20 InitializeComponent(); 21 } 22 bool stateFlag = false;//暂停标识 23 Random r = new Random();//随机数对象 24 25 private void startNum_Click(object sender, EventArgs e) 26 { 27 if (!stateFlag) 28 { 29 startNum.Text = "暂停";//改变按钮文本 30 stateFlag = true; 31 Thread th = new Thread(StartRandom);//开启线程 32 th.IsBackground = true;//标识后台线程 33 th.Start(); 34 35 } 36 else 37 { 38 startNum.Text = "开始"; 39 stateFlag = false; 40 } 41 42 43 } 44 /// <summary> 45 /// 生成随机数方法,使用控件的invoke方法刷新label,实现数字滚动 46 /// </summary> 47 private void StartRandom() 48 { 49 int r1; 50 int r2; 51 int r3; 52 while (stateFlag) 53 { 54 r1 = r.Next(0, 10);//生成label1的随机数 55 r2 = r.Next(0, 10);//生成label2的随机数 56 r3 = r.Next(0, 10);//生成label3的随机数 57 if (label1.InvokeRequired) 58 { 59 this.label1.Invoke(new Action<Label, string>(setvalue), this.label1, r1.ToString()); 60 } 61 if (label2.InvokeRequired) 62 { 63 this.label2.Invoke(new Action<Label, string>(setvalue), this.label2, r2.ToString()); 64 } 65 66 if (label3.InvokeRequired) 67 { 68 this.label3.Invoke(new Action<Label, string>(setvalue), this.label3, r3.ToString()); 69 } 70 } 71 } 72 73 /// <summary> 74 /// 改变label数字 75 /// </summary> 76 /// <param name="lab"></param> 77 /// <param name="lbvalue"></param> 78 private void setvalue(Label lab, string lbvalue) 79 { 80 lab.Text = lbvalue; 81 } 82 83 84 private void Form1_Load(object sender, EventArgs e) 85 { 86 //Control.CheckForIllegalCrossThreadCalls = false;关闭跨线程检测。。。 87 //Label.CheckForIllegalCrossThreadCalls = false; 88 startNum.Text = "开始"; 89 } 90 } 91 }
总结:
其实2、3原理基本一致,后来找问题时候发现其实是用委托的时候代码放错了位置(滚去面壁!)
控件只能由创建它的线程来访问。其他线程想访问必须调用该控件的Invoke方法。Invoke有两个参数,一个是委托方法,一个是参数值。
是用事件还是用委托(随便的啦~)。
菜鸟第一篇笔记,写得比较烂,勿转勿喷,仅此献给新手
时间: 2024-10-27 18:09:32