C#使用中的-Invoke

C#: Control中的Invoke的使用。Invoke和BeginInvoke一般是在支路线程中调用,用来更新主界面。Invoke在拥有此控件的基础窗口句柄的线程上执行指定的委托;BeginInvoke在创建控件的基础句柄的线程上异步执行指定的委托。

Invoke的调用:

using System;
	using System.Threading;
	using System.Windows.Forms;
	namespace test20180818
	{
	    public partial class Form1 : Form
	    {
	        public Form1()
	        {
	            InitializeComponent();
	        }
	        private Thread invokeThread;
	        private delegate void InvokeDelegate();
	        private void button1_Click(object sender, EventArgs e)
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "1");
	            invokeThread = new Thread(new ThreadStart(StartMethod));
	            invokeThread.Start();
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"2");
	        }
	        private void StartMethod()
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"3");
	            button1.Invoke(new InvokeDelegate(invokeMethod));
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"4");       
	        }
	        private void invokeMethod()
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"5");
	         }
	      }
	    }

执行的结果为:1-》并行的结果2和3-》5-》4
1------>2和StartMethod()中的3同时得到----->3执行完,不管2有没有执行完,InvokeThread把消息封送(Invoke)给UI线程,然后自己等待)---->UI线程处理完button1_Click后,处理InvokeThread封送过来的消息,执行InvokeMethod方法,即5,处理往后UI线程切换到invokeThread线程,最后得到4。

BeginInvoke的写法同上,把Invoke替换成BeginInvoke即可测试结果。

    using System;
	using System.Threading;
	using System.Windows.Forms;
	namespace test20180818
	{
	    public partial class Form1 : Form
	    {
	        public Form1()
	        {
	            InitializeComponent();
	        }
	        private Thread beginInvokeThread;
	        private delegate void beginInvokeDelegate();
	        private void button1_Click(object sender, EventArgs e)
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "1");
	            beginInvokeThread = new Thread(new ThreadStart(StartMethod));
	            beginInvokeThread.Start();
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"2");
	        }
	        private void StartMethod()
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"3");
	            button1.BeginInvoke(new InvokeDelegate(beginInvokeMethod));
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"4");       
	        }
	        private void beginInvokeMethod()
	        {
	            MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"5");
	         }
	      }
	    }

1在UI线程上执行----->beginInvokeThread线程开始执行,UI继续执行代码段2,并发地invokeThread执行代码段3-------------->不管UI有没有执行完代码段2,这时beginInvokeThread线程把消息封送给UI,自己并不等待,继续向下执行-------->UI处理完button1_Click消息后,处理beginInvokeThread线程封送过来的消息。
能够区分他们分别是执行在哪个线程上的。有线程UI/线程begininvokeThread/线程invokeThread
注:以上1、2、3、4、5分别是输出打印的字符所在段落的代码

C#为控件单独开辟了一个线程,当另外一个线程的方法需要修改控件或者调用控件的方法时,需要通过控件的InvokeRequired方法来进行。比如,当另一个线程想调用控件的方法时:

  //定义委托
private delegate void SendCallBack(List<byte[]> bufferList,bool  feedback);
//Send方法属于某个窗口
private void Send(List<byte[]> bufferList,bool feedback) {
            if (this.InvokeRequired) {                          //跨线程调用时的执行逻辑
                try {
                    SendCallBack cb = new SendCallBack(Send);
                    this.Invoke(cb,bufferList,feedback);
                } catch(Exception ex) {
                    MessageBox.Show(ex.Message);
                }        
            } 
           else 
           {
           //不是跨线程调用此方法时的执行逻辑
           }      }
           
private void serialPort1_DataReceived(object sender,SerialDataReceivedEventArgs e) {
    Send(bufferlist,true);
}  

控件的InvokeRequired属性:bool值,为true时表示调用Send方法的是另一个线程,此时需要将Send方法传送给一个委托让委托所在的线程来代替执行Send方法;为false时表示Send的调用者没有跨线程调用Send方法,此时直接执行else中的代码即可。
串口的DataReceived事件和Send方法所属的窗口不在同一个线程,因此在serialPort1_DataReceived事件中调用Send方法时就会执行Send方法中if块中的代码。

this.InvokeRequired
说白了,判断当前线程是否是UI线程。
如果this.InvokeRequired = true,你需要通过this.Invoke()传递委托去操作界面。否则直接操作即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[2\]的代码展示了在C#使用Invoke方法的示例。Invoke方法用于在UI线程上执行指定的委托方法。在引用\[2\]的代码,通过实例化一个委托对象,并将其传递给BeginInvoke方法来调用委托方法。BeginInvoke方法会在UI线程上异步执行委托方法。 引用\[3\]的代码展示了另一种使用Invoke方法的示例。与BeginInvoke方法不同,Invoke方法会在UI线程上同步执行委托方法。在引用\[3\]的代码,通过实例化一个委托对象,并将其传递给Invoke方法来调用委托方法。 总结来说,C#的Invoke方法用于在UI线程上执行委托方法。BeginInvoke方法是异步执行,而Invoke方法是同步执行。这两种方法都可以用于在多线程环境下更新UI界面。 #### 引用[.reference_title] - *1* *3* [C#的invoke和begininvoke](https://blog.csdn.net/thebesttome/article/details/7589856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c#Invoke方法](https://blog.csdn.net/yangdayededaye/article/details/49147933)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值