• InvokeRequired与Invoke


    在多线程应用中将会涉及不同的线程访问同一控件的问题,C#中禁止跨线程直接访问控件。某个控件在被创建时就记下了是谁创建了它,即它的创建线程。如果从另一个线程调用该控件,那么必须使用控件的 Invoke 方法来将调用封送现在调用它的线程。(Invoke方法是控件的方法)

    到底是哪个线程要使用该控件呢?需要用InvokeRequired来询问一下,如果当前调用线程不是控件的创建线程,则为 true;否则为 false。

    例子:

    代码段前提是lb是一个label控件,在主线程创建(不用了解具体在哪个线程,反正和RunTimer不在一个线程),RunTimer方法是在另一个线程创建,这时候我们需要RunTimer方法调用主线程上的label控件。

      private delegate void RunTimeDelegate();
            private void RunTime()
            {
                if (lb.InvokeRequired)
                {
                    RunTimeDelegate d = RunTime;
                    lb.Invoke(d);//Invoke方法是控件的,这里相当于把RunTime方法交于了委托d,
                    //d中相当于把RunTimer方法从线程中提取出来放到委托中,此时控件的Invoke方法就可以
                     //    调用委托中的和RunTimer相同方法,这样控件使用RunTimer方法就在控件的线程中使用的。
                }
                else
                {
                    time = endTime - TimeSpan.Parse(DateTime.Now.ToString("HH:mm:ss"));
                    lb.Text = time.ToString();
                }
    
            }

     ,这里添加几个实例,第一个是无参数传递,跨线程控制picturebox1控件

      private delegate void DrawOnePicDelegate();//跨线程调用pictureBox1
            public void DrawOnePicture()
            {
                if (pictureBox1.InvokeRequired)//如果控件被非本线程调用,则返回true
                {
                    DrawOnePicDelegate d = new DrawOnePicDelegate (DrawOnePicture);//将方法放入委托
                    this.pictureBox1.Invoke(d);//从从控件创建线程中调用该方法
                }
                else
                {
                          //方法
                    }                
    

      另一个是带参数传递控制listbox的内容,传入的参数就是list中应该显示的text

      delegate void AddItemCallback(string text);
    
            //这种方法演示如何在线程安全的模式下调用Windows窗体上的控件。
            private void AddItem(string text)
            {
                if (this.listBox1.InvokeRequired)
                {
                    AddItemCallback d = new AddItemCallback(AddItem);
                    this.Invoke(d, new object[] { text });
                }
                else
                {
                    this.listBox1.Items.Add(text);
                }
            }
    

      

    添加一个自己在实践中遇到的问题:问题大致描述:首先开辟一个线程,线程中方法实现在label控件上实现秒计数。

    这里添加最开始错误的代码:

                G_th = new System.Threading.Thread(ShowText);
                G_th.IsBackground = true;//设置线程为后台线程
                G_th.Start();//开始执行线程
            
    //以上为建立一个线程,线程名字为G_th。
            
            private delegate void ShowTextDelegate();
            public void ShowText()
            {
                int P_int_count = 0;
                while (true)
                {
                    P_int_count = ++P_int_count > 1000000 ? 0 : P_int_count;//计数器累加 
                    if (lb_time.InvokeRequired)
                    {
                        ShowTextDelegate d = new ShowTextDelegate(ShowText);
                        lb_time.Invoke(d);
                    }
                    else
                    {                 
                        lb_time.Text = P_int_count.ToString();
                    }
                    //  Thread.Sleep(1000);//线程睡眠1秒
                }
            }
                       
    

      上述代码运行时会出现卡死,原因在于while的循环问题,至于为什么,我也没搞懂,哪位大神看到了也可以帮小弟解答下,后来我改了代码成为下面的样子,运行成功。我把while的循环放在了外面,label的委托仅仅只判断label的引用线程,所以,在平时工作中,应当注意,尽量不要在控件的委托中调用循环。

               G_th.IsBackground = true;//设置线程为后台线程
               G_th.Start();//开始执行线程
    public void AddCount() { P_int_count = 0; while (true) { P_int_count = ++P_int_count > 1000000 ? 0 : P_int_count;//计数器累加 ShowText(); Thread.Sleep(1000);//线程睡眠1秒 } } private delegate void ShowTextDelegate(); public void ShowText() { if (lb_time.InvokeRequired) { ShowTextDelegate d = new ShowTextDelegate(ShowText); lb_time.Invoke(d); } else { lb_time.Text = P_int_count.ToString();//窗体中显示计数 } }

      

  • 相关阅读:
    2331: [SCOI2011]地板 插头DP
    APIO2018 铜滚记
    2827: 千山鸟飞绝 非旋treap
    3682: Phorni 后缀平衡树 线段树
    4712: 洪水 基于链分治的动态DP
    20180507小测
    4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap
    5312: 冒险 线段树 复杂度分析
    5210: 最大连通子块和 动态DP 树链剖分
    4513: [Sdoi2016]储能表 数位DP
  • 原文地址:https://www.cnblogs.com/liyulongBlog/p/7978649.html
Copyright © 2020-2023  润新知