namespace _018_跨线程访问控件方法
{
    public partial class 跨线程访问控件方法 : Form
    {
        public 跨线程访问控件方法()
        {
            InitializeComponent();
            //方法1:不推荐
            //Control.CheckForIllegalCrossThreadCalls=false;
        }
        //方法2-控件对象.Invoke(Action<>,参数)
        private void bt1_Click(object sender, EventArgs e)
        {           
            Task t1 = Task.Run(() =>
            {
                for (int i = 1; i < 100; i++)
                {
                    Thread.Sleep(500);
                    //True则表示与当前线程不在同一个线程中
                    if (this.txtBox1.InvokeRequired)
                    {
                        //使用Invoke方法进行传递数据,Action有参数string类型,st表示要传的参数,无返回值
                        //有返回值的要使用Func
                        //Invoket同步执行,会卡UI
                        this.txtBox1.Invoke(new Action<string>((st) =>
                        {
                            this.txtBox1.Text = st;
                        }), i.ToString());//将要传递的参数写到Lambda表达式后面,即将i的值传递给(st)
                    }
                }               
            });
        }
        //方法3-控件对象.BeginInvoke(Action<>,参数)
        private void bt2_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                for(int i = 1;i < 100; i++)
                {
                    Thread.Sleep(1000);
                    //True则表示与当前线程不在同一个线程中
                    if (this.txtBox2.InvokeRequired)
                    {
                        //使用BeginInvoke方法进行传递数据,Action有参数string类型,st表示要传的参数,无返回值
                        //有返回值的要使用Func
                        //BeginInvoket异步执行,不会卡UI
                        this.txtBox2.BeginInvoke(new Action<string>((st) =>
                        {
                            this.txtBox2.Text += st+"、";
                            //this.txtBox3.Text += st + "、";//每个值后面+顿号
                        }),i.ToString());//将要传递的参数写到Lambda表达式后面,即将i的值传递给(st)
                    }
                }
            });
        }
        //方法4-Invoke((MethodInvoker)delegate
        //MethodInvoker 是一个无参数、无返回值的委托类型,用于表示可以被调用的方法
        //在多线程编程中,特别是在 Windows 窗体应用程序中,MethodInvoker 常用于安全地更新 UI 控件,
        //它可以被用作给 Invoke 和 BeginInvoke 方法传递的委托。
        private void bt3_Click(object sender, EventArgs e)
        {
            Task.Run(() => 
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread.Sleep(1000);
                    //True则表示与当前线程不在同一个线程中,判断多个控件
                    if (this.txtBox3.InvokeRequired|| this.txtBox3.InvokeRequired)
                    {
                        Invoke((MethodInvoker)delegate
                        {
                            this.txtBox3.Text = i.ToString();
                            this.txtBox4.Text = i.ToString();
                        });
                    }
                }               
            });
        }       
    }
}