【C#】【Thread】SynchronizationContext线程间同步
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线程间同步的更多相关文章
- c++11 线程间同步---利用std::condition_variable实现
1.前言 很多时候,我们在写程序的时候,多多少少会遇到下面种需求 一个产品的大致部分流程,由工厂生产,然后放入仓库,最后由销售员提单卖出去这样. 在实际中,仓库的容量的有限的,也就是说,工厂不能一直生 ...
- C#线程间同步无法关闭
用C#做了个线程间同步的小程序,但每次关闭窗口后进程仍然在,是什么原因? 解决方法: 要加一句 线程.IsBackground = true; 否则退出的只是窗体 上面的方法没看懂... MSDN上说 ...
- Linux系统编程(29)——线程间同步(续篇)
线程间的同步还有这样一种情况:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行.在pthread库中通过条件变 ...
- linux线程间同步方式汇总
抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin loc ...
- conditon_variable(条件变量)用于线程间同步
conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒, ...
- rtt学习之线程间同步与通信
一 线程间的同步与互斥:信号量.互斥量.实践集 线程互斥是指对于临界区资源访问的排它性,如多个线程对共享内存资源的访问,生产消费型对产品的操作.临界区操作操作方法有: rt_hw_interrupt_ ...
- Linux进程间通信与线程间同步详解(全面详细)
引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496linux下进程间通信的几种主要手段简介: 1. 管道(Pipe)及有名管道( ...
- 线程间同步之 semaphore(信号量)
原文地址:http://www.cnblogs.com/yuqilin/archive/2011/10/16/2214429.html semaphore 可用于进程间同步也可用于同一个进程间的线程同 ...
- (Java多线程系列二)线程间同步
Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...
随机推荐
- Sharepoint学习笔记—习题系列--70-573习题解析 -(Q85-Q87)
Question 85You create a Microsoft .NET Framework console application that uses a Representational St ...
- Android Java类编写规范+优化建议
本文仅是我个人在实际开发中习惯的编写方式,当然这种方式也是来自很多官方的推荐,所以在一定程度上是可以被模仿套用的.本文将不定期更新~ 零.指导原则 优先保证可读性,不要过分追求代码艺术和效率 在可读性 ...
- 安卓第十四天笔记-内容提供者(ContentProvider)
安卓第十四天笔记-内容提供者(ContentProvider) ContentProvider--内容提供者 1.ContentProvider简介 ContentProvider是不同应用程序之间进 ...
- android 音乐播放器简单实现
package com.zhangbz.musicplayer; import java.io.File; import android.app.Activity; import android.me ...
- redis中set命令的源码分析
首先在源码中的redis.c文件中有一个结构体:redisCommand redisCommandTable[],这个结构体中定义了每个命令对应的函数,源码中的set命令对应的函数是setComman ...
- Github学习之路-初出茅庐,接触Github,了解Github
一.了解GitHub 作为一个在线协作网站,GitHub允许程序员们分享和协力于开源项目的工作. GitHub不仅是一个分享开源创作并与其它程序员合作的好地方,你也可以从GitHub上收到自己作品的 ...
- redis 五种数据结构详解(string,list,set,zset,hash)
redis 五种数据结构详解(string,list,set,zset,hash) Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存 ...
- c# App.Config详解
c# App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序. 配置文件的根 ...
- Hadoop,Vertica环境搭建
本打算使用mapr的虚拟机在里面进行开发,使用eclipse进行调试,它的问题是,有时候服务不能完全起来, 如jobtracker和tasktracker,cldb没有起来,重启服务有可能解决. 但另 ...
- WEB安全--Google Hacking
通常我们用Google查询一些我们测试站点的一些信息,Google提供了一系列的搜索语句,下面我为大家详细的介绍一下! 常用语法: site:指定域名 intext:正文中存在关键字的网页 intit ...