Обновленный Вопрос (указать проблему правильно)ApplicationSettingsBase ConfigurationErrorsException несколько сборок
Я использую LIB, который реализует класс, производный от ApplicationSettingsBase
.
namespace MyLib {
public sealed class GlobalLibSettings : ApplicationSettingsBase
{
[UserScopedSetting, DefaultSettingValue("true")]
public bool SimpleProperty{
get { return (bool) this["SimpleProperty"]; }
set {
this["SimpleProperty"] = value;
Save();
}
}
}
}
Теперь я использую эту библиотеку в другом проекте. Проекты также содержат по крайней мере один класс, который происходит от ApplicationSettingsBase
.
namespace MyProject {
public sealed class ProjectSettings : ApplicationSettingsBase
{
[UserScopedSetting, DefaultSettingValue("true")]
public bool AnotherProperty{
get { return (bool) this["AnotherProperty"]; }
set {
this["AnotherProperty"] = value;
Save();
}
}
}
}
Теперь оба класса, вытекающие из ApplicationSettingsBase
хранения своих свойств же user.config
файла. Приложение и lib используют несколько задач, и если две задачи выполняют (например) свойство setter в то же время, я получаю следующее исключение. Обе задачи пытаются выполнить действие записи в то же время ...
System.Configuration.ConfigurationErrorsException occurred
BareMessage=Beim Laden einer Konfigurationsdatei ist ein Fehler aufgetreten.: Der Prozess kann nicht auf die Datei "... _xneb3g43uoxqiagk4ge5e4hea1vxlina\1.0.4.862\user.config" zugreifen, da sie von einem anderen Prozess verwendet wird.
Filename=..._xneb3g43uoxqiagk4ge5e4hea1vxlina\1.0.4.862\user.config
HResult=-2146232062
Line=0
Message=Beim Laden einer Konfigurationsdatei ist ein Fehler aufgetreten.: Der Prozess kann nicht auf die Datei "..._xneb3g43uoxqiagk4ge5e4hea1vxlina\1.0.4.862\user.config" zugreifen, da sie von einem anderen Prozess verwendet wird. (..._xneb3g43uoxqiagk4ge5e4hea1vxlina\1.0.4.862\user.config)
Source=System.Configuration
StackTrace:
bei System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
InnerException:
HResult=-2147024864
Message=Der Prozess kann nicht auf die Datei "_xneb3g43uoxqiagk4ge5e4hea1vxlina\1.0.4.862\user.config" zugreifen, da sie von einem anderen Prozess verwendet wird.
Source=mscorlib
StackTrace:
bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
bei System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
bei System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
bei System.Configuration.Internal.InternalConfigHost.StaticOpenStreamForRead(String streamName)
bei System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.OpenStreamForRead(String streamName, Boolean assertPermissions)
bei System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.OpenStreamForRead(String streamName)
bei System.Configuration.ClientConfigurationHost.OpenStreamForRead(String streamName)
bei System.Configuration.BaseConfigurationRecord.RefreshFactoryRecord(String configKey)
я могу воспроизвести его с помощью следующего сценария:
var settings1 = new GlobalLibSettings();
var settings2 = new ProjectSettings();
Task.Factory.StartNew(()=>{
while(true) settings1.SimpleProperty = !settings1.SimpleProperty;
});
Task.Factory.StartNew(()=>{
while(true) settings2.AnotherProperty = !settings2.AnotherProperty;
});
Теперь я искал для реализации защиты доступа к файлу user.config
,
Решение:
я нашел рабочий раствор. CustomApplicationSettingsBase
блокирует одновременные задачи.
public sealed class GlobalLibSettings : CustomApplicationSettingsBase
и
public sealed class ProjectSettings : CustomApplicationSettingsBase
с:
namespace MyLib {
public static class LockProvider
{
public static object AppSettingsLock { get; } = new object();
}
public class CustomApplicationSettingsBase : ApplicationSettingsBase
{
public override object this[string propertyName] {
get {
lock (LockProvider.AppSettingsLock) {
return base[propertyName];
}
}
set {
lock (LockProvider.AppSettingsLock) {
base[propertyName] = value;
}
}
}
public override void Save() {
lock (LockProvider.AppSettingsLock) {
base.Save();
}
}
public override void Upgrade() {
lock (LockProvider.AppSettingsLock) {
base.Upgrade();
}
}
}
}
Спасибо за вашу помощь!
Реализация блокировки поможет только в том случае, если все потоки используют один и тот же экземпляр вашего класса. –
Как создать экземпляр GlobalAppSettings? У вас есть один или несколько экземпляров GlobalAppSettings? –
@Mathew Jibin и Michal Komorowski: вы оба правы, теперь я вижу свою ошибку. Мне понадобится глобальный объект блокировки для управления доступом к файлам из нескольких реализаций. Я проверю его днем. – WPFGermany