翻译,原文地址:http://help.agi.com/AGIComponents/html/CalculationContext.htm
STK组件中的许多计算需要各种上下文信息。定义了什么闰秒?如何建模地球的定向,以便在地固系和惯性系之间进行转换?这种上下文信息可以在任何需要它的地方传递,但这会很麻烦。计算上下文是存储和查找此类信息的一致位置,因此不需要将其作为参数传递给方法。
计算上下文和Facets
计算上下文在某些方面与全局变量或静态类类似。像全局变量或静态类一样,它可以从任何地方方便地访问。然而,计算上下文要灵活得多。每个线程都可以有自己的计算上下文,而不是为整个应用程序提供全局变量或静态类的单个副本。这允许不同的线程以不同的方式建模地固系和惯性系之间的转换,同时仍然允许需要进行转换的代码使用正确的转换,而不传递任何其他内容。
因此,计算上下文对于上下文信息非常有用,这些信息通常在整个应用程序中是一致的,但有时需要在不同的执行线程中有所不同。例如,一个多用户Web应用程序处理两个不同用户的请求时,可能会根据用户的偏好,为一个用户使用一个地球模型,为另一个用户使用另一个地球模型。
一般来说,您不会直接与CalculationContext
类型进行交互,而是使用CalculationContextFacets
,其中每一个都表示驻留在CalculationContext
中的一块上下文信息。Facets
通常有一个静态的GetFromContext
方法来从当前的CalculationContext
中检索当前有效的实例。例如,要检索CentralBodiesFacet
实例,请使用其GetFromContext
方法:
CentralBodiesFacet centralBodies = CentralBodiesFacet.GetFromContext();
如果上下文中不存在CentralBodiesFacet
实例,则将创建并返回一个新实例。
类似地,您可以向CalculationContext
添加实例,如下代码所示,该代码使用CentralBodiesFacet.UseIncurrentContext()
方法:
CentralBodiesFacet centralBodies = new CentralBodiesFacet();
// 按需配置centralBodies
centralBodies.UseInCurrentContext();
以下Facets
随STK组件提供:
- CentralBodiesFacet
- LeapSecondsFacet
计算上下文和多线程
如前所述,每个线程都有自己的计算上下文。这就提出了一个问题:新线程如何获取计算上下文?他们从哪里得到的?
第一次创建线程时,它没有计算上下文。第一次尝试通过访问实例属性或调用方面的GetFromContext
方法访问计算上下文时,将为线程创建默认的CalculationContext
实例。
通过设置DefaultForNewContexts
属性,可以更改为新线程创建的默认上下文。例如,下面的代码使当前上下文成为新线程使用的默认上下文。
CalculationContext.DefaultForNewContexts = CalculationContext.Instance;
每当STK组件本身创建新的线程(例如并行化过境计算)时,它总是将启动计算的计算上下文复制到实际执行计算的线程中。通过使用BackgroundCalculation
类型,您可以非常容易地为自己的线程执行相同的操作。BackgroundCalculation
与.NET BackgroundWorker
类非常相似,只是它会自动将计算上下文复制到Worker线程中。BackgroundCalculation
与BackgroundWorker
还有其他一些不同之处。有关更多信息,请参阅参考文档。
如果不使用BackgroundCalculation
,则仍可以手动复制计算上下文。在启动新线程之前,请复制当前计算上下文:
CalculationContext contextForThread = CopyForAnotherThread.Copy(CalculationContext.Instance);
然后,将新实例传递给线程:
Thread thread = new Thread(ThreadEntryPoint);
thread.Start(contextForThread);
最后,在线程入口点函数的顶部,将当前计算上下文设置为从主线程传递的上下文:
public static void ThreadEntryPoint(object parameter)
{
CalculationContext calculationContext = (CalculationContext)parameter;
CalculationContext.Instance = calculationContext;
// 线程从这开始实际工作
}