zoukankan      html  css  js  c++  java
  • 关于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有两个参数,一个是委托方法,一个是参数值。

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

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

  • 相关阅读:
    如何选择Html.RenderPartial和Html.RenderAction
    [转]使用 HTML5 WebSocket 构建实时 Web 应用
    基于.NET平台常用的框架整理
    0303
    XMLHTTP
    0120如何合并两个使用 System.Xml 使用 Visual C#.NET 的 XML 文档中的数据
    后台动态创建datatable0115
    笔记1126ASP.NET面试题(转)
    笔记1015
    数组与ARRAYLIST的关系与区别(转)
  • 原文地址:https://www.cnblogs.com/Junius-G/p/4687852.html
Copyright © 2011-2022 走看看