1、通过SynchronizationContext的Post/Send方法
主要原理是:在线程执行过程中,需要更新到UI控件上的数据不再直接更新,而是通过UI线程上下文的Post/Send方法,将数据以异步/同步消息的形式发送到UI线程的消息队列;UI线程收到该消息后,根据消息是异步消息还是同步消息来决定通过异步/同步的方式调用SetLabel1Post方法直接更新自己的控件了。
从本质讲,向UI线程发送的消息并是不简单数据,而是一条委托调用命令。
1.1、获取UI线程同步上下文(在窗体构造函数或FormLoad事件中)
SynchronizationContext synchronizationContext =null;System.Timers.Timer timer =newSystem.Timers.Timer();publicForm1(){InitializeComponent();
synchronizationContext = SynchronizationContext.Current;
timer.Interval +=100;
timer.Elapsed += Timer_Elapsed;
timer.Start();}
1.2、定义更新UI控件的方法
privatevoidSetLabel1Post(object text){this.label1.Text = text.ToString();}
1.3、在定时线程中调用更新UI控件的方法
Boolean flag =false;privatevoidTimer_Elapsed(object sender,System.Timers.ElapsedEventArgs e){string str;if(flag){
str ="数据回读值:0x0001";
flag =false;}else{
str ="寄存器回读值:0x0088";
flag =true;}
synchronizationContext.Post(SetLabel1Post, str);}
2、通过Invoke/BeginInvoke方法
本质上还是把线程中要提交的消息,通过控件句柄调用委托交到UI线程中去处理。
2.1、定义定时线程
System.Timers.Timer timer =newSystem.Timers.Timer();publicForm1(){InitializeComponent();
timer.Interval +=100;
timer.Elapsed += Timer_Elapsed;
timer.Start();}
2.2、采用跨线程委托
privatevoidSetLabelText(Label label,string text){try{if(label.InvokeRequired){MethodInvoker mi =delegate(){
label.Text = text;};
label.Invoke(mi);}else{
label.Text = text;}}catch(Exception e){
Console.WriteLine(e.Message);}}
2.3、在定时处理函数更新控件
Boolean flag =false;privatevoidTimer_Elapsed(object sender,System.Timers.ElapsedEventArgs e){string str;if(flag){
str ="数据回读值:0x0001";
flag =false;}else{
str ="寄存器回读值:0x0086";
flag =true;}SetLabelText(label2, str);}
2.4、解决出现“访问已释放句柄“的异常的方法
while(!this.label3.IsHandleCreated){if(this.label3.Disposing ||this.label3.IsDisposed)return;}
3、通过设置窗体属性,取消非法跨线程调用检查来避免"线程间操作无效异常"
通过设置该属性为false简单的屏蔽了该异常(非线程安全,建议不使用)。
publicForm1(){InitializeComponent();//取消非法跨线程调用检查
Control.CheckForIllegalCrossThreadCalls =false;}
版权归原作者 大浪淘沙胡 所有, 如有侵权,请联系我们删除。