利用SynchronizationContext.Current在线程间同步上下文

本文主要是介绍利用SynchronizationContext.Current在线程间同步上下文,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简而言之就是允许一个线程和另外一个线程进行通讯,SynchronizationContext在通讯中充当传输者的角色。另外这里有个地方需要清楚的,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。

在多线程操作时往往需要切回某个线程中去工作,等完成后再切回来。如主UI线程中创建了一个子线程A。A中添加了委托事件。UI线程中向A线程的类注册了事件,当A线程触发事件时去修改UI上的属性如TEXT。这个时候往往要在UI线程向子线程注册的事件方法中使用控件的invoke方法才能访问UI线程中的控件,因为这些注册的事件(委托)方法代码虽然看似写在UI线程的Form类中,但实际上是注册在了子线程A的事件中,它们是会被子线程A触发事件时在子线程内部执行的。这样,我们不得不在主UI线程的类的注册事件方法中通过控件的invoke方法才能访问控件,这样做十分麻烦。我们想和系统的控件事件一样,直接在注册的事件方法中访问控件。那么我们想,有没有一个机制能让子线程在执行UI线程委托过来的(注册的事件)方法中直接访问控件本身呢?答案是肯定的。对过SynchronizationContext.Current 。

SynchronizationContext.Current 能得到当前被主UI线程接管过的对象SynchronizationContext。

这个对象有一个方法:SynchronizationContext.Send(SendOrPostCallback d,object state)

d 为一个没有返回值,并且具有一个Object类型传入参数的委托(SendOrPostCallback )

state 为执行这个委托时的参数(object)


你现在需要在子线程运行的时候利用SynchronizationContext.Current 得到SynchronizationContext对象,然后在需要切回UI线程的地方使用:

SynchronizationContext.Send(SendOrPostCallback d,object state);就可实现将委托的方法切回到UI线程上去执行。


注意:SynchronizationContext的对象不是所有线程都被附加的,只有UI主线程会被附加。对于UI线程来说,是如何将SynchronizationContext这个对象附加到线程上的呢?

在Form1 form = new Form1()之前,SynchronizationContext对象是为空,而当实例化Form1窗体后,SynchronizationContext对象就被附加到这个线程上了。所以可以得出答案了:当Control对象被创建的同时,SynchronizationContext对象也会被创建并附加到线程上。所有在使用时,一定要等窗体InitializeComponent(); 这个完成后 它才能得到一个不这NULL的对象

可以参考这里:http://lzy3169421.blog.163.com/blog/static/1135452772009357251417/


最后SynchronizationContext的Sendt()和Post()二个方法的区别:

Send() 是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用UI线程执行,等UI线程执行完成后子线程才继续执行。

Post() 是在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调UI线程,子线程不等待UI线程的完成而直接执行自己下面的代码。

详细的推荐看这二篇文章:

线程之间的通讯---SynchronizationContext

奇妙的SynchronizationContext


[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //在类里声明SynchronizationContext ,如果其它类要访问它,可将它声明为静态  
  2. SynchronizationContext sync;  
  3.   
  4. //-----------------------------------------  
  5.   
  6. //在UI线程可以接触到这个类的地方得到它  
  7. sync = SynchronizationContext.Current;  
  8.   
  9.   
  10. //----------------------------------------  
  11.   
  12.   
  13. //声明一个要带回给UI线程的委托,然后使用SynchronizationContext的Send方法  
  14. //PushNewMsgEvent 是一个定义好的事件  
  15. private void PushNewMsg(object sender, InfoBox iBox)  
  16.         {//这个方法是被子线程执行的。  
  17.             if (PushNewMsgEvent != null)  
  18.             {  
  19.                   
  20.                 SendOrPostCallback sp = new SendOrPostCallback(aaa);    //声明SynchronizationContext.Send方法里需要用到的委托  
  21.                 List<object> tmp = new List<object>(); //将多个参数封装到一个对象中,以便给委托传递object参数  
  22.                 tmp.Add(sender);  
  23.                 tmp.Add(iBox);  
  24.                   
  25.                 sync.Send(sp, tmp);    //发送给主UI线程来执行sp这个委托  
  26.         
  27.             }  
  28.         }  
  29.   
  30. //一个要带回给UI线程执行的委托方法  
  31.         private void aaa(object obj)  
  32.         {//这个方法如果没有上面的SynchronizationContext.Send,也将是在子线程中执行,但由于上面的把这个方法委托给了主UI去执行,所以它将被运行在UI线程上              
  33.                 List<object> tmp = (List<object>)obj;   
  34.                 User user = (User)tmp[0];   
  35.                 InfoBox ib = (InfoBox)tmp[1];   
  36.                 PushNewMsgEvent(user, ib); //这里已经变成在主UI线程中来触发执行这个事件了,不再是在子线程中触发。   
  37.         }  

···

这篇关于利用SynchronizationContext.Current在线程间同步上下文的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/383819

相关文章

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

Mac备忘录怎么导出/备份和云同步? Mac备忘录使用技巧

《Mac备忘录怎么导出/备份和云同步?Mac备忘录使用技巧》备忘录作为iOS里简单而又不可或缺的一个系统应用,上手容易,可以满足我们日常生活中各种记录的需求,今天我们就来看看Mac备忘录的导出、... 「备忘录」是 MAC 上的一款常用应用,它可以帮助我们捕捉灵感、记录待办事项或保存重要信息。为了便于在不同

查看MySql主从同步的偏移量方式

《查看MySql主从同步的偏移量方式》:本文主要介绍查看MySql主从同步的偏移量方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 1.mysql的主从同步方案mysqlphp为了在实现读写分离,主库写,从库读mysql的同步方案主要是通过从库读取主库的binl

MySQL主从同步延迟问题的全面解决方案

《MySQL主从同步延迟问题的全面解决方案》MySQL主从同步延迟是分布式数据库系统中的常见问题,会导致从库读取到过期数据,影响业务一致性,下面我将深入分析延迟原因并提供多层次的解决方案,需要的朋友可... 目录一、同步延迟原因深度分析1.1 主从复制原理回顾1.2 延迟产生的关键环节二、实时监控与诊断方案

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

MySQL使用binlog2sql工具实现在线恢复数据功能

《MySQL使用binlog2sql工具实现在线恢复数据功能》binlog2sql是大众点评开源的一款用于解析MySQLbinlog的工具,根据不同选项,可以得到原始SQL、回滚SQL等,下面我们就来... 目录背景目标步骤准备工作恢复数据结果验证结论背景生产数据库执行 SQL 脚本,一般会经过正规的审批

Linux搭建Mysql主从同步的教程

《Linux搭建Mysql主从同步的教程》:本文主要介绍Linux搭建Mysql主从同步的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux搭建mysql主从同步1.启动mysql服务2.修改Mysql主库配置文件/etc/my.cnf3.重启主库my

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键