SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。

  需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContext context = SynchronizationContext.Current;

  那什么时候会用到呢?

  在多线程操作时往往需要切回某个线程中去工作,等完成后再切回来。

  如主UI线程中创建了一个子线程A。A中添加了委托事件。UI线程中向A线程的类注册了事件,当A线程触发事件时去修改UI上的属性如TEXT。

  这个时候往往要在UI线程向子线程注册的事件方法中使用控件的invoke方法才能访问UI线程中的控件,因为这些注册的事件(委托)方法代码虽然看似写在UI线程的Form类中,但实际上是注册在了子线程A的事件中,它们是会被子线程A触发事件时在子线程内部执行的。这样,我们不得不在主UI线程的类的注册事件方法中通过控件的Invoke方法才能访问控件,这样做十分麻烦。我们想和系统的控件事件一样,直接在注册的事件方法中访问控件。那么这个时候就可以用SynchronizationContext了。

  SynchronizationContext.Send(SendOrPostCallback d,object state);

  SynchronizationContext.Post(SendOrPostCallback d,object state);

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

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

注意:

  SynchronizationContext的对象不是所有线程都被附加的,只有UI主线程会被附加。

  对于UI线程来说,是如何将SynchronizationContext这个对象附加到线程上的呢?

  在Form1 form = new Form1()之前,SynchronizationContext对象是为空,而当实例化Form1窗体后,SynchronizationContext对象就被附加到这个线程上了。

  所以可以得出答案了:当Control对象被创建的同时,SynchronizationContext对象也会被创建并附加到线程上。所以在使用时,一定要等窗体InitializeComponent(); 这个完成后 它才能得到一个不是NULL的对象.

  

  那么SynchronizationContext的Send()和Post()二个方法有什么区别呢?

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

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

  

例子:

        /// <summary>
/// 这里需要在主线程里定义,
/// 并在主线程获得context = SynchronizationContext.Current
/// </summary>
private SynchronizationContext context;
/// <summary>
/// 窗体加载
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
//此处就是之前提的在主线程获得SynchronizationContext
context = SynchronizationContext.Current;
//之后可以开线程了
Thread thread = new Thread(new ThreadStart(Start));
thread.IsBackground = true;
thread.Start();
}
/// <summary>
/// 线程操作
/// </summary>
private void Start()
{
for(int i=;i<;++i)
{
//这边即可正常调用主界面的控件了
context.Send(operation, i);//正确
//按原先直接应用,因为使用到控件会报错
operation(i);//报错
Thread.Sleep();
}
}
/// <summary>
/// 线程操作
/// </summary>
/// <param name="obj"></param>
private void operation(object obj)
{
textBox1.AppendText(obj.ToString() + "\r\n");
}

参考文章:http://blog.csdn.net/iloli/article/details/16859605

最新文章

  1. Unity3D 事件
  2. makefile示例
  3. hihocoder 1037 数字三角形
  4. DATEDIFF()(转)
  5. Python爬虫:获取糗事百科笑话
  6. Tomcat部署项目通过—IP地址:端口访问
  7. ios 第三方qq授权登陆,第一次登陆后,再次登陆,失效
  8. AngularJs 基础(60分钟入门) (转)
  9. 【转载】GPIO模拟i2c通信
  10. jq实现上传头像并实时预览功能
  11. MTK 快速开机 技术详解
  12. django(权限、认证)系统——User模型
  13. caffe 根据txt生成多标签LMDB数据
  14. Day2----《Pattern Recognition and Machine Learning》Christopher M. Bishop
  15. freemark使用总结
  16. Chromium(Chrome) Sandbox Details
  17. Centos6.5部署Rsyslog+LogAnalyzer中文乱码解决
  18. FreeBie—免费设计师专用素材网
  19. [GO]解决golang.org/x/ 下包下载不下来的问题
  20. StringBuffer类和String 类的 equals 和 ==

热门文章

  1. oracle断电重启之ORA-00600[4194]
  2. Android-Selector用法
  3. Jenkins部署.net自动化构建
  4. 关于NSDate和NSDateFormatter的几个常用方法
  5. IOS 登陆界面的简单编写(通过NSNotificationCenter)
  6. iOS开发笔记2:单例模式(singleton)
  7. Erlang 虚拟机 BEAM 指令集之内存管理相关的指令
  8. HTTP Content-type
  9. 迅为4412开发板支持AVIN视频输入/AV监控摄像头输入模块
  10. ubuntu apache2服务器配置