惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
The Cloudflare Blog
IT之家
IT之家
V
V2EX
雷峰网
雷峰网
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
Engineering at Meta
Engineering at Meta
S
SegmentFault 最新的问题
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
小众软件
小众软件
博客园 - 叶小钗
Blog — PlanetScale
Blog — PlanetScale
C
Check Point Blog
A
About on SuperTechFans
B
Blog
月光博客
月光博客
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI

博客园 - Kevin-moon

在IE中本地浏览与服务器浏览同一Html后,出现了奇异的结果 如何避免JQuery Dialog的内存泄露 JQuery另类视角-动态执行脚本的BUG JQuery另类视角-动态扩展对象 - Kevin-moon - 博客园 如何重构代码-简单、灵活的实现对象复制 如何重构代码-重构计划 如何重构代码-思路和方法 谈谈多线程的思维方式 简单的数据移动算法(C#) [ASP.NET MVC]-理解Routing 笑死人的十项大奖 深入APM,实现自己的APM [Windbg基础]-了解Symbols 深入线程,实现自定义的SynchronizationContext 重温ASP.NET的配置信息(简单、常用) 线程之间的通讯---SynchronizationContext "对象"到"山寨对象"的完整转换 我真的就只能在远方看你吗?!!! "测试驱动开发(TDD)" 动态进行"自定义公式"计算
奇妙的SynchronizationContext
Kevin-moon · 2009-01-16 · via 博客园 - Kevin-moon

     上一篇中已经讲了SynchronizationContext 的一些内容,现在让我们更加深入地去了解它!
     继上篇中的问题"在UI线程上对SynchronizationContext的使用,可以适用于其他线程呢?"
     OK,我们把它放置在非UI线程上,这是你用SynchronizationContext.Current的属性来获取,你会发现你得到的是null,这时候,你可能会说,既然它不存在,那么我自己创建一个SynchronizationContext对象,这样就没问题了吧!?可是,最后它并不会像UI线程中那样去工作。
    让我们看下面的例子:

class Program
{
    
private static SynchronizationContext mT1 = null;static void Main(string[] args)
    {
        
// log the thread id
        int id = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine(
"Main thread is " + id);// create a sync context for this thread
        var context = new SynchronizationContext();
        
// set this context for this thread.
        SynchronizationContext.SetSynchronizationContext(context);// create a thread, and pass it the main sync context.
        Thread t1 = new Thread(new ParameterizedThreadStart(Run1));
        t1.Start(SynchronizationContext.Current);
        Console.ReadLine();
    }
static private void Run1(object state)
    {
        
int id = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine(
"Run1 Thread ID: " + id);// grab  the sync context that main has set
        var context = state as SynchronizationContext;// call the sync context of main, expecting
        
// the following code to run on the main thread
        
// but it will not.
        context.Send(DoWork, null);while (true)
            Thread.Sleep(
10000000);
    }
static void DoWork(object state)
    {
        
int id = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine(
"DoWork Thread ID:" + id);
    }
}

输出的结果:

Main thread is 10
Run1 Thread ID: 
11
DoWork Thread ID:
11

     注意上面的输出结果,DoWork和Run1是运行在同一线程中的,SynchronizationContext并没有把DoWork带入到主线程中执行,为什么呢?!
我们可以先看SynchronizationContext的原码(SynchronizationContext原代码):

Code

注意Send和Post的部分:

public virtual void Send(SendOrPostCallback d, Object state)
{
    d(state);
}
public virtual void Post(SendOrPostCallback d, Object state)
{
    ThreadPool.QueueUserWorkItem(
new WaitCallback(d), state);
}

     Send就是简单在当前的线程上面去调用委托来实现,而Post是通过线程池来实现。
     这时候你也许会奇怪,为什么UI线程上,SynchronizationContext就发挥了不同的作用呢!其实在UI线程中使用的并不是SynchronizationContext这个类,而是WindowsFormsSynchronizationContext这个东东。

     它重写了Send和Post方法。至于它是如何重写实现的,这个我也不是很了解,也没有找到相关的文章,只是知道通过"消息泵"来实现的,但是细节就不清楚了,如果大家知道的话,可以告诉下我,我很想了解下!呵呵
     最后,我画了一副图,让我们更加清楚地了解SynchronizationContext在UI线程和一般线程之间的不同,
     

     上一篇:线程之间的通讯---SynchronizationContext