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

【C#】【Thread】SynchronizationContext线程间同步的更多相关文章

  1. c++11 线程间同步---利用std::condition_variable实现

    1.前言 很多时候,我们在写程序的时候,多多少少会遇到下面种需求 一个产品的大致部分流程,由工厂生产,然后放入仓库,最后由销售员提单卖出去这样. 在实际中,仓库的容量的有限的,也就是说,工厂不能一直生 ...

  2. C#线程间同步无法关闭

    用C#做了个线程间同步的小程序,但每次关闭窗口后进程仍然在,是什么原因? 解决方法: 要加一句 线程.IsBackground = true; 否则退出的只是窗体 上面的方法没看懂... MSDN上说 ...

  3. Linux系统编程(29)——线程间同步(续篇)

    线程间的同步还有这样一种情况:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行.在pthread库中通过条件变 ...

  4. linux线程间同步方式汇总

    抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin loc ...

  5. conditon_variable(条件变量)用于线程间同步

    conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒, ...

  6. rtt学习之线程间同步与通信

    一 线程间的同步与互斥:信号量.互斥量.实践集 线程互斥是指对于临界区资源访问的排它性,如多个线程对共享内存资源的访问,生产消费型对产品的操作.临界区操作操作方法有: rt_hw_interrupt_ ...

  7. Linux进程间通信与线程间同步详解(全面详细)

    引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496linux下进程间通信的几种主要手段简介: 1. 管道(Pipe)及有名管道( ...

  8. 线程间同步之 semaphore(信号量)

    原文地址:http://www.cnblogs.com/yuqilin/archive/2011/10/16/2214429.html semaphore 可用于进程间同步也可用于同一个进程间的线程同 ...

  9. (Java多线程系列二)线程间同步

    Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...

随机推荐

  1. 【读书笔记】iOS-引用计数

    Cocoa采用了一种称为引用计数的技术,有时也叫做保留计数.每个对象有一个与之相关联的整数,称作它的引用计数器或保留计数器.当某段代码需要访问一个对象时,该代码将该对象的保留计数器值加1,表示“我要访 ...

  2. iOS edgesForExtendedLayout、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets属性详解

    edgesForExtendedLayout: 在IOS7以后 ViewController 开始使用全屏布局的,而且是默认的行为通常涉及到布局,就离不开这个属性 edgesForExtendedLa ...

  3. iOS之UI--转场动画

    1.什么是转场动画?    就是从一个场景转换到另一个场景,像导航控制器的push效果,就是一个转场.    2.如何创建转场动画    创建转场动画    CATransition *anim = ...

  4. 网络请求的基本知识《极客学院 --AFNetworking 2.x 网络解析详解--1》学习笔记

    网络请求的基本知识   我们网络请求用的是HTTP请求 Http请求格式:请求的方法,请求头,请求正文 Http请求的Request fields:请求的头部,以及被请求头部的一些设置 Http请求的 ...

  5. windows 2008 r2 下面搭建 iis+sql server +php5.6 环境遇见的一些问题记录一下

    由于web服务器以前在iis下部署有几个网站,现在这个项目开发又是用的php,本来php+mysql+iis应该很简单随便在网上能搜索出来很多,但是,由于以前那个web网站是用的sqlserver数据 ...

  6. 【SVN】Unable to connect to a repository at URL 'svn://localhost/Test'

    早上配置SVN,但是这次不是那么顺利... 环境: Windows 7 SVN服务器端:CollabNetSubversion-server-1.8.13-1 SVN客户端:TortoiseSVN_V ...

  7. maven 错误No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format

    [INFO] Scanning for projects... [INFO] ------------------------------------------------------------- ...

  8. Java 读取指定目录下的文件名和目录名

    需求:读取指定目录下的文件名和目录名 实现如下: package com.test.common.util; import java.io.File; public class ReadFile { ...

  9. HDU 4045 Machine scheduling (组合数学-斯特林数,组合数学-排列组合)

    Machine scheduling Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  10. FAQ-Ubuntu12.04 15.04禁止移动介质自动播放

    网上有有很多关于Ubuntu10.04关闭移动介质自动播放的方法,包括在文件管理器里面设置或者使用gconf-editor,但是从12.04开始这两种方法都不再好用了,关于移动介质的处理方法被移到了S ...