当前位置: 首页 > 工具软件 > Invoke > 使用案例 >

Invoke的用法

虞承泽
2023-12-01

原文:http://blog.sina.com.cn/s/blog_70bf5798010185i4.html

在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,多个线程对一个变量同时访问是非常危险的

所以在编程中我们可以只用Invoke 和 BeginInvoke 来解决这个问题,使多线程中安全的更新界面显示。

正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。

在编程中,由于界面的更新是很频繁的,所以应尽可能的吧操作对丢给工作线程,尽量让更新界面的UI线程工作量变少

 
下面说明BeginInvoke的用法
更新窗体中的TextBox..
 
思路:在主窗口中定义一个委托,其他线程需要进行界面更新的操作时就调用这个委托

如果要在子线程中创建其他窗体,也应该有UI线程来创建,方法类似 

namespace test
{
    public partial class Form1 : Form
    {

        //定义一个委托
        public delegate void MyInvoke(string str1,string str2);
        public Form1()
        {
            InitializeComponent();
        }

        public void DoWork()
        {

            //实例化委托
            MyInvoke mi = new MyInvoke(UpdateForm);

            //启动委托,让主线程执行操作
            this.BeginInvoke(mi, new Object[] {"我是文本框","haha"});
        }
        public void UpdateForm(string param1,string parm2)
        {
            this.textBox1.Text = param1+parm2;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(DoWork));
            thread.Start();
        }
    }
}

 
下面做法是不可取的,不能再多个线程访问同一个变量
//启动一个线程
Thread thread=new Thread(new ThreadStart(DoWork));
thread.Start();

//线程方法
private void DoWork()
{
    this.TextBox1.Text="我是一个文本框";
}

===================================================================
经常还会看见另外一种写法,如:
        protected void setMsg(string pStr)
        {
            if (textBox1.InvokeRequired)  
            {
                getTextBack st = new getTextBack(setMsg);
                this.Invoke(st, new object[] { pStr });  
                  
            }  
            else  
            {
                textBox1.Text += "\n" + pStr + "\n";  
            }  
        }  
经过debug,可以看出,第一次程序会跑if下面的语句,然后跳出,此时已经启动了委托,接下来,程序会第二次跑进setMsg,但这此textBox1.InvokeRequired为false,说明此次是主线程开始操作了,于是程序会跳过if语句,执行else
 类似资料: