【发布时间】:2011-12-24 13:50:51
【问题描述】:
我为我打算在 WPF 应用程序中使用的 Ninject DI 容器创建了一个包装器。我希望它是线程安全的,以防我需要在单独的线程中打开新窗口,但我对使用 volatile 关键字和锁定感到困惑。据我所知,锁定非常容易理解,但我不支持使用 volatile 关键字。从我的谷歌搜索结果中,我了解到 volatile 关键字可确保在多线程环境中对指定实例进行安全读取访问,但在更改指定实例占用的内存空间时不提供任何安全性。我将我的解决方案与一些线程安全的单例模式示例结合起来,并提出了这个可以作为服务定位器的包装器:
public class NinjectResolver
{
private static object syncRoot = new object();
private static volatile NinjectResolver instance = null;
private static volatile IKernel kernel = null;
public static NinjectResolver GetInstance()
{
lock (syncRoot)
{
if (instance == null)
instance = new NinjectResolver();
}
return instance;
}
static NinjectResolver()
{
lock (syncRoot)
{
if (kernel == null)
kernel = new StandardKernel();
}
}
public void AddBindings(Dictionary<Type, Type> bindings)
{
lock (syncRoot)
{
foreach (var binding in bindings)
{
Type IType = binding.Key;
Type ImplementationType = binding.Value;
kernel.Bind(IType).To(ImplementationType);
}
}
}
private NinjectResolver()
{
}
/// <summary>
/// Resolves All dependencies for requested instance and returns that instance
/// </summary>
/// <typeparam name="T">Requested Implementation type</typeparam>
/// <returns>Instance of Implementation type</returns>
public T Resolve<T>()
{
return kernel.TryGet<T>();
}
/// <summary>
/// Resolves property injection dependencies in already instantiated Implementation types
/// </summary>
/// <param name="obj">Specified instance of implementation type</param>
public void Inject(object obj)
{
kernel.Inject(obj);
}
}
我的问题是:我是否需要在指定位置使用锁定,因为初始化将在 App.xaml.cs 内部进行(第一次调用 GetInstance() )并且这些静态字段是否需要声明为 volatile 或者我可以省略该部分,因为它们在此构造中或多或少是只读的。如果有人能对此有所了解,我将不胜感激。
【问题讨论】:
-
您可以省略 volatile,原因您已经知道。锁定没问题。另外,当我读到“有人可以撕碎一些光”时,我咯咯地笑着,想着如果只有查克·诺里斯(Chuck Norris)能读到这个:)
-
好吧,我们都有自己的“特殊时刻”……谢谢您的回答。
标签: c# wpf multithreading .net-4.0 ninject