2009-04-13 50 views
9

是否有一种简单的方法通过线程安全接口访问基于System.Configuration的自定义配置数据,而不需要每个执行上下文来加载/重新加载配置信息,这在计算上会很繁琐?线程安全地使用System.Configuration

System.Configuration类,像大多数(全部?)其他类微软的.Net库文件中,被标注有下列线程安全的信息:

任何公共静态(在Visual Basic中的Shared)成员这种类型是线程安全的。 任何实例成员不保证是线程安全的。

通过我的这个阅读,ConfigurationSection对象从ConfigurationManager.GetSection(string)和其他类似的方法(例如OpenExeConfiguration(string exePath).GetSection(string))不能被认为是线程安全返回,因此不应由多个执行环境中使用。这禁止将ConfigurationSection存储在一个本来是线程安全的单例中,因为虽然对section对象的访问可能是安全的,但对象上的成员本身并不安全。

然而,多次调用GetSection可能需要重新解析配置文件并分配新的ConfigurationSection实例,这些实例的开销很高,因为配置在初始化后可能不会改变。此外,将配置数据复制到已经成为线程安全的另一个对象似乎打破了首先使用内置配置包的主要优点之一(可轻松访问类型转换和验证的配置信息,而不需要太多的样板文件码)。

那么,有没有办法使用System.Configuration线程安全的方式,而不诉诸多余的解析和配置节的分配?即使您通过System.Configuration接口访问它,执行自己的ConfigurationSection是否使您免于提供由Microsoft提供的担保(如果是这样,您将如何在访问基础ConfigurationSection的索引器时将其实施为线程安全的是否需要访问配置的数据)?

回答

5

从GetSection返回的实例不是线程安全的。这意味着您需要添加锁定代码才能在单例中使用它。

多次调用不会重新解析文件,除非文件已更改。数据缓存在内存中。

您的线程安全问题很容易通过使用锁定解决(我不确定您需要,除非您在运行时更改配置),并且没有性能问题。

+0

我一直有一个IIS服务器过去5个月随机崩溃,因为这一点。不知道为什么(崩溃是MSCorLib中的堆栈溢出),直到它发生在我的开发机器上,并且appsettings调用导致了它。我认为这回答了我的问题。谢谢。 – 2013-08-22 20:58:03

0

ConfigurationManager.GetSection(string)是一个公共静态成员,并且由于msdn声明'此类型的任何公共静态(Visual Basic中的Shared)成员都是线程安全的',因此可以认为使用它是安全的。

至于性能,我会愿意假设MS已经使它非常高效,只是使用它们的功能。请记住:过早优化是邪恶的根源。