Skip to content

Mac OS X snapshot shortcuts

Key Combination Result
Command+Shift+3 Capture entire screen and save as a file
Command+Control+Shift+3 Capture entire screen and copy to the clipboard
Command+Shift+4 Capture dragged area and save as a file
Command+Control+Shift+4 Capture dragged area and copy to the clipboard
Command+Shift+4 then Space bar Capture a window, menu, desktop icon, or the menu bar and save as a file
Command+Control+Shift+4 then Space bar Capture a window, menu, desktop icon, or the menu bar and copy to the clipboard

重置Finder的Open With菜单的脚本

OS X 10.6有个bugs,Open With菜单会因为关联应用软件更新而出现重复项。下面这个脚本可以帮到你。
run the following terminal command

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user

it will rebuild your launch services database and the duplicates should go away.

Tagged

CCR源码分析-从最简单的Sample开始

前面提到的MSDN文章的配套例子中,有一个方法非常简单,我们就从这里入手开始分析CCR吧。

private static void SpawnDemo(DispatcherQueue dq)
{
        // Construct an arbiter from a delegate & activate it on the DispatcherQueue
        // This is simiar to calling ThreadPool.QueueUserWorkItem
        Arbiter.Activate(dq, Arbiter.FromHandler(() => Msg(“Handler”)));
        HitEnter();
}

]]>

CCR源码分析-CCR架构

CCR,并发与协调运行时(Concurrency and Coordination Runtime)。从名字里我们就可以知道,这个东东是用来简化并发程序设计的。为何要并发呢?因为我们有多个任务需要处理,如果能同时做就会充分利用硬件而减少处理的时间。自然的,CCR也是以“任务”为核心进行设计的,CCR中的代码也可以分为如下几个功能:描述任务、生成任务、调度任务和执行任务。

描述任务

对于计算机来说一个任务就是一段需要执行的代码,于是CCR有一个对任务的最抽象描述:ITask接口

image

任务被封装在ITask实例中,当CCR调度这个任务实例去执行之后,CCR会调用ITask.Execute方法来执行该任务。在ITask接口之下,派生出来各种各样的Task

Tasks

本节讨论的是CCR的整体结构,后面我们会具体讨论这些classes。

 

生成任务

对于计算机来说,任务都是类似的:按给定的参数执行一个给定的方法。但是对于程序员来说,往往并非这么简单。从时序上来讲,任务可以分为这么几种情况:算法和参数都已经齐备的、已知算法等待参数的和已知参数等待算法的。对于第一种情况,直接使用Thread或者ThreadPool也可以很方便的解决问题,当然CCR也提供了相应的支持。对于后面两种情况,CCR使用了计算过程与参数分离描述的方法来解决。计算机的程序的作用就是处理流程相对固定的事务,往往计算逻辑是有限的而参数是变化无穷的。于是CCR将计算过程与参数分离开来,调用者不需要知道如何处理这些参数,甚至不需要知道是谁何时来进行处理,它只需要把要计算的数据发送到一个特定的地方即可,而这些数据会被可信赖的得以处理。当计算过程接收到适当的参数的时候,也就生成了任务。CCR中Port和PortSet类型就是这样的参数存储器。ReceiverTask及其子类则是封装计算过程的类型,Port可以被注册到相应的ReceiverTask中,当有其他用户向Port中投递元素时,就会生成任务并放入相应的DispatcherQueue中等待调度。

image

 

 

调度任务

需要执行的任务是有先来后到、轻重缓急的,同时计算机的CPU资源是有限度,每个核(包括超线程的逻辑核)在同一时间只能处理一个线程。这时候就需要进行一定的调度。为了充分利用CPU,自然是要使用多线程来执行任务。如果不使用CCR,我们也可以用.net内置的Thread和ThreadPool都可以用的并行任务调度,其中又数ThreadPool用起来比较简单,直接把要执行的方法丢进去就好了。但是这简单的背后也存在问题,虽然是解决了任务的先来后到,但是没办法分轻重缓急了,ThreadPool坚持认定CPU面前人人平等的原则,晚来的就是要侯着等先到底执行完。直接用Thread也有问题,就是无法很容易的控制线程的数量以及重用线程,而线程本身又是一个比较重型的资源,反反复复的创建和销毁很影响效率。为了解决这些问题CCR提出了自己的任务调度方案。DispatcherQueue。

image

DispatcherQueue本质上就是一个任务队列,它使得任务按照先来后到的顺序执行。但是你可以创建多个DispatcherQueue,比如把高优先级的任务放入一个队列,把普通优先级的放入另外一个,那么高优先级的任务不需要等待前面所有普通优先级任务都执行完毕才得到执行。

执行任务

Dispatcher是CCR的执行单元,也是一个线程池的实现。既然是线程池,那么就必然有它所要管理的工作线程,TaskExecutionWorker类封装了Dispatcher中工作线程所要执行的方法以及一些必要的处理。

image

]]>

CCR源码分析-分析环境准备

由于CCR的源码并没有直接公开,所以我们需要借助一些工具来窥探它的秘密。             

       

分析CCR需要如下的工具

MS Robotic Studio Express 2008R2,这个就不用解释了,安装它就是为了获得CCR

Reflector & FileDisassembler,Reflector有两个作用,一个是用来把CCR的dll文件反编译到C#语言,第二个是直接对CCR进行一些分析,而这些分析在VS中并不容易。FileDisassembler是Reflector的一个插件,用来把反编译的结果导出为一个C#工程。

Visual C# 2008 Express or Visual Studio 2010 beta2(推荐,因为VS 2010大大增强了多线程调试能力)

以上工具皆可合法的免费获得

 

CCR源码和例子程序

Microsoft.Ccr.Core.dll是我们本次要研究的对象。为了分析和调试的方便,我们需要把它用Reflector和FileDisassembler反编译。注意,反编译后的源码可能有些问题,下面记载了几个比较重要的修改:
1. Resource文件。我们需要先删除Reflector生成的Resource1.cs,然后新建一个名为Resource1.resx的资源文件,把Reflector生成的Microsoft.Ccr.Core.resx中的字符串全部复制到Resource1.resx中,最后删除原来的Microsoft.Ccr.Core.resx
2. Dispatcher.cs中有两个静态变量的初始化顺序不正确,需要吧TraceSwitchCore的声明和初始化语句放在文件最顶端。

Sample Code,为了统一起见,我选择了MSDN Mag中的这篇文章中的代码。
解压Sample Code后,用VS创建一个CCRDemo的project,把解压得到的代码添加到CCRDemo项目中,再把反编译得到的CCR源码工程也加入这个Solution中,最后给CCRDemo添加CCR的引用。如果能编译并运行CCRDemo,则说明我们的分析环境已经构建好了。

]]>

CCR相关的Channel 9视频

重读《Patterns of enterprise application architecture》

经典之所以是经典,就在于你每次重温都会有新的发现和体会。5年后重读这本书,依然觉得收获颇丰。

Transaction Script

Transaction Script是一种比较直接的实现方法。一个业务操作对应一个public方法。而这个方法中包含了从业务逻辑计算到持久化的所有细节(你当然可以在这个方法中调用一些子方法来减少代码重复)。这个方式适用于比较简单的系统,配合DAAB可以实现一个性能较好,代码易读的程序。

Domain Model

大师推荐使用充血模型。对于java来说,充血模型也许是个梦魇,但是对于C# 3.0来说,充血模型实现起来并不那么困难,因为有partail class/extension

DSS服务组件

DSS简介

原文链接

也许你还不知道的一些关于App Domain的事

Domain Neutral Assemblies,虽然这个咚咚的名字字面意思挺清楚,但是之前从未接触过,于是特意搜索了一番,东拉西扯之下,也学到了一些关于App Domain的有趣的东西,在这里总结记录一下。

首先,App Domain是什么?MSDN里给出了一堆文字来说明。其实简单的说,App Domain就是是一个轻量级的进程。
  • Domain Neutral Assemblies
顾名思义,Domain Neutral Assemblies就是不跟特定App Domain相关而可以跨越多个App Domains的Assembly。大家都知道,一般情况下,我们自己创建App Domain都是为了动态的加载/卸载一些Assemblies,但是Domain Neutral Assemblies比较特殊,它是不能随着App Domain被unload的。而且处于性能的考虑,Domain Neutral Assemblies只会被JIT一次,JIT之后的代码会存储在Share Domain中。但是Assemblies相关的数据依然会存储在每个加载它的App Domains中。例如:某个Application中有几个App Domains,而Assembly A被作为一个Domain Neutral Assembly加载。A中有一个类型T,T有一个静态变量S,那么T.S在每个App Domain中的值是分别存储的,修改一个App Domain中的T.S不会改变另一个App Domain中的T.S。
  • Friend Assemblies
就像C++中的friend classes,在.net 2.0中引入了friend assemblies。通过给Assembly A设置InternalsVisibleToAttribute属性来设置B是A的Friend Assembly。这样B中的类型就可以访问A中的internal类型和internal成员(方法/属性/子段/事件等)。
  • 如何加载Assemblies到一个App Domain
.net提供了多种方法加载一个Assembly到App Domain,但是推荐使用Assembly.Load方法来做这件事。剩下的方法还有:Assembly.LoadFrom, Assembly.ReflectionOnlyLoad, Assembly.ReflectionOnlyLoadFrom。还有一些看起来跟加载Assembly无关的方法,其实也有加载Assembly的副作用,比如Type.GetType, AppDomain.CreateInstance, AppDomain.CreateInstanceAndUnwrap。
比较特别的一个方法是AppDomain.Load,这个方法是不推荐在Managed Code中调用的。因为如果你在App Domain A中调用了App Domain B的Load方法,B.Load其实是将Assembly加载到了App Domain B中,这还不是最糟糕的,最糟糕的是,AppDomain的Load方法会返回Assembly的引用到A,还记得吧,App Domain之间是隔离的,A并不能直接调用B中的方法和类型而是要通过Marshal的方式来通讯,但是由于Assembly不是从MarshalByRef继承,所以Assembly对象必须以Marshal by value的方式返回到A中,这时A会再次根据自己的配置来定位和加载这个Assembly,最好的情况下就是B和A都加载了这个Assembly,如果运气不好,A和B设置的搜索路径不同而A恰好找不到这个Assembly,boom,一个FileNotFoundException就被抛出啦。
  • Reflection-Only Context

通过Assembly的ReflectionOnlyLoad/ReflectionOnlyLoadFrom方法可以把一个Assembly加载到Reflection-Only context中,顾名思义,在这个上下文中的Assembly只能用于反射而不能用于执行。通过这个方法可以加载不同CLR版本的Assembly,我想著名的Reflector应该就是用的这种办法吧。唯一一个例外就是mscorlib,即使用ReflectionOnlyLoad也是无法加载不同CLR版本的mscorlib。
参考资料:
http://blogs.msdn.com/junfeng/archive/2004/08/05/208375.aspx
http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx
http://msdn.microsoft.com/en-us/library/43wc4hhs.aspx


]]>