关于Winform中控件的跨线程访问

闲着没事想起来用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有两个参数,一个是委托方法,一个是参数值。

是用事件还是用委托(随便的啦~)。

菜鸟第一篇笔记,写得比较烂,勿转勿喷,仅此献给新手

原文地址:https://www.cnblogs.com/Junius-G/p/4687852.html