概述 这几天太忙没时间写博客,今天回家就简单的看了下ThreadPool的
源码,发现有一个好玩的东西,叫做”执行上下文“,拽名叫做:”ExecutionContext“。 一:ThreadPool的大概流程。 第一步:它会调用底层一个helper方法。 第二步:走进这个helper方法,我们会发现有一个队列,并且这个队列的item必须是QueueUserWorkItemCallback的实例,然后这就激发了我的 兴趣,看看QueueUserWorkItemCallback到底都有些什么? 第三步:走到QueueUserWorkItemCallback实例的时候,会依次把callback,state参数给当前类的字段,并且有一个好玩的地方的就是根据 ExecutionContext.IsFlowSuppressed()来判断要不要把”当前
线程的上下文“给”调用线程“?这个放在后面讲,然后我们看到了一个 IThreadPoolWorkItem.ExecuteWorkItem()方法,里面有ContextCallback委托的调用,也许这个就是队列中每一项中要调用的方法。 第四步:然后我们再回到第二步中的 ThreadPoolGlobals.workQueue.Enqueue(callback, true)方法进去看看,并且我们的callback,state都被封装成了 QueueUserWorkItemCallback放到队列中了,从这个Enqueue方法中,我们看到了一个this.EnsureThreadRequested(),走到方法里面去了之后,这时候急迫想去看ThreadPool.RequestWorkerThread()方法,但它是个extern方法,不过从名字上看就是请求工作线程去执行,所以并没有真实的发现到所谓的线程池这个东西。(由于不能窥全貌,可能有些说的不太对) 好了,上面的剖析大概就这样了,其实所有的方法都封装成了底层的一个类放在一个队列中,应该是用上面的for来挑选空闲的工作线程去执行我们的任务,里面还有很多代码,比较复杂,一时也看不懂什么。 二:执行上下文刚才第三步说到了”执行上下文“,看到这个方法里面有一个if条件,然后看到有一个 ExecutionContext.IsFlowSuppressed()方法,从名字上就可以看出叫”阻止流动“,如果为否的话,就用Capture来抓当前线程的”上下文信息“,然后我们就顺藤摸瓜的往下看,从这个方法来看,我们依次去抓取调用线程的”安全设置“,”宿主设置“,”同步信息“,“逻辑调用”,并且可以看到logicalCallContext有值的话,会做一个copy的 *** 作。 其实这个logicalCallContext非常有意思,里面是一个KV结构,源码里面也说了,只要我不IsFlowSuppressed,那么主线程的上下文会flow到工作线程,那么logicalCallContext怎么设置呢?其实在C#里面的CallContext里面的LogicalSetData和LogicalGetData就可以做这些事情。1 class Program2 {3 static void Main(string[] args)4 {5 CallContext.LogicalSetData("name", "ctrip");67 Thread.CurrentThread.IsBackground = true;89 ThreadPool.QueueUserWorkItem((o) =>10 {11 var t = Thread.CurrentThread.ManagedThreadId;1213 var result = CallContext.LogicalGetData("name");1415 Console.WriteLine("我是工作线程: Name:" + result);1617 });1819 Console.Read();20 }21 } 可以看到我在主线程设置的值被工作线程读到了,是不是很有意思,给我们线程间传值提供了另一种方法,刚才我们也看到,一旦IsFlowSuppressed了,那么context就返回null,也就阻止了将logicCallContext的信息传递给工作线程,可以用ExecutionContext.SuppressFlow()做到,下面具体看一看。1 class Program2 {3 static void Main(string[] args)4 {5 CallContext.LogicalSetData("name", "ctrip");67 //阻止logical数据流动8 ExecutionContext.SuppressFlow();910 Thread.CurrentThread.IsBackground = true;1112 ThreadPool.QueueUserWorkItem((o) =>13 {14 var t = Thread.CurrentThread.ManagedThreadId;1516 var result = CallContext.LogicalGetData("name");1718 Console.WriteLine("我是工作线程: Name:" + result);1920 });2122 Console.Read();23 }24 } 现在结论也出来了,去Capture主线程的上下文是需要很多的代码量,所以如果工作线程用不到主线程的这些信息,那么你应该做到显示关闭,这样对工作线程的性能来说有很大的好处。
这几天太忙没时间写博客,今天回家就简单的看了下ThreadPool的源码,发现有一个好玩的东西,叫做”执行上下文“,拽名叫做:”ExecutionContext“。
第一步:它会调用底层一个helper方法。
第二步:走进这个helper方法,我们会发现有一个队列,并且这个队列的item必须是QueueUserWorkItemCallback的实例,然后这就激发了我的
兴趣,看看QueueUserWorkItemCallback到底都有些什么?
第三步:走到QueueUserWorkItemCallback实例的时候,会依次把callback,state参数给当前类的字段,并且有一个好玩的地方的就是根据
ExecutionContext.IsFlowSuppressed()来判断要不要把”当前线程的上下文“给”调用线程“?这个放在后面讲,然后我们看到了一
个 IThreadPoolWorkItem.ExecuteWorkItem()方法,里面有ContextCallback委托的调用,也许这个就是队列中每一项中要调用
的方法。
第四步:然后我们再回到第二步中的 ThreadPoolGlobals.workQueue.Enqueue(callback, true)方法进去看看,并且我们的callback,state都被封装成了
QueueUserWorkItemCallback放到队列中了,从这个Enqueue方法中,我们看到了一个this.EnsureThreadRequested(),
好了,上面的剖析大概就这样了,其实所有的方法都封装成了底层的一个类放在一个队列中,应该是用上面的for来挑选空闲的工作线程去执行我们
的任务,里面还有很多代码,比较复杂,一时也看不懂什么。
刚才第三步说到了”执行上下文“,看到这个方法里面有一个if条件,然后看到有一个 ExecutionContext.IsFlowSuppressed()方法,从名字上
就可以看出叫”阻止流动“,如果为否的话,就用Capture来抓当前线程的”上下文信息“,然后我们就顺藤摸瓜的往下看,从这个方法来看,我们依次
去抓取调用线程的”安全设置“,”宿主设置“,”同步信息“,“逻辑调用”,并且可以看到logicalCallContext有值的话,会做一个copy的 *** 作。
其实这个logicalCallContext非常有意思,里面是一个KV结构,源码里面也说了,只要我不IsFlowSuppressed,那么主线程的上下文会flow到
工作线程,那么logicalCallContext怎么设置呢?其实在C#里面的CallContext里面的LogicalSetData和LogicalGetData就可以做这些事情。
Main( CallContext.LogicalSetData(, Thread.CurrentThread.IsBackground = ThreadPool.QueueUserWorkItem((o) => t = Console.Writeline( + }可以看到我在主线程设置的值被工作线程读到了,是不是很有意思,给我们线程间传值提供了另一种方法,刚才我们也看到,一旦IsFlowSuppressed
了,那么context就返回null,也就阻止了将logicCallContext的信息传递给工作线程,可以用ExecutionContext.SuppressFlow()做到,下面具体
看一看。
Main( CallContext.LogicalSetData(, Thread.CurrentThread.IsBackground = ThreadPool.QueueUserWorkItem((o) => t = result = CallContext.LogicalGetData( Console.Writeline( + }现在结论也出来了,去Capture主线程的上下文是需要很多的代码量,所以如果工作线程用不到主线程的这些信息,那么你应该做到显示关闭,这样
对工作线程的性能来说有很大的好处。
总结 以上是内存溢出为你收集整理的简单看看ThreadPool的源码以及从中看出线程间传值的另一种方法全部内容,希望文章能够帮你解决简单看看ThreadPool的源码以及从中看出线程间传值的另一种方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)