InvokeRequired与Invoke

摘要:
使用InvokeRequired询问。如果当前调用线程不是控件的创建线程,则为true;否则,这是错误的。privatevoidAddItem{if{AddItemCallbackb=newAddItemCallback;this.Invoke;}else{this.listBox1.Items.Add;}}添加我在实践中遇到的问题:问题的一般描述:首先,打开一个线程,线程中的方法实现标签控件的第二个计数。

在多线程应用中将会涉及不同的线程访问同一控件的问题,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();//窗体中显示计数 } }

  

免责声明:文章转载自《InvokeRequired与Invoke》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇局域网WEB方式实现TTS实时语音合成阿里云云盾安全事件提醒:挖矿程序下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

由浅入深TheradLocal

线程并发:在多线程并发的场景下 传递数据:我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量 线程隔离:每个线程的变量都是独立的,不会相互影响 常用方法 方法声明 描述 ThreadLocal() 创建ThreadLocal对象 public void set(T value) 设置当前线程绑定的局部变量 public...

Java任务调度

四种任务调度的 Java 实现: Timer ScheduledExecutor 开源工具包 Quartz 开源工具包 JCronTab Timer 相信大家都已经非常熟悉 java.util.Timer 了,它是最简单的一种实现任务调度的方法,下面给出一个具体的例子: 清单 1. 使用 Timer 进行任务调度 package com.ibm.s...

Android优化总结

极力推荐文章:欢迎收藏Android 干货分享 文章转载网络 原文地址如下:https://juejin.im/post/5d072dbc51882540b7104709 1.OOM和崩溃优化 1.2 ANR优化 ANR的产生需要满足三个条件 主线程:只有应用程序进程的主线程响应超时才会产生ANR; 超时时间:产生ANR的上下文不同,超时时间也会...

jvm参数优化

一、HotSpot JVM 提供了三类参数 现在的JVM运行Java程序(和其它的兼容性语言)时在高效性和稳定性方面做的非常出色。例如:自适应内存管理、垃圾收集、及时编译、动态类加载、锁优化等。虽然有了这种程度的自动化(或者说有这么多自动化),但是JVM仍然提供了足够多的外部监控和手动调优工具(允许命令行参数可以在JVM启动时传入到JVM中)。在有错误或低...

Mysql主从同步的实现原理与配置实战

1、什么是mysql主从同步? 当master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库。 2、主从同步有什么好处? 水平扩展数据库的负载能力。 容错,高可用。Failover(失败切换)/High Availability 数据备份。 3、主从同步的原理是什么? 首先我们来了解master-slave的体系结构。如下图:...

公司线上虚拟机大量GC导致STW和CPU飙升--抽丝剥茧定位的过程

作者: bryan31 原链接:https://www.v2ex.com/t/701513 背景 公司线上有个 tomcat 服务,里面合并部署了大概 8 个微服务,之所以没有像其他微服务那样单独部署,其目的是为了节约服务器资源,况且这 8 个服务是属于边缘服务,并发不高,就算宕机也不会影响核心业务。 因为并发不高,所以线上一共部署了 2 个 tomcat...