При работе в многопоточной среде в приложении могут возникать ошибки (генерироваться исключения) при создании нового ObjectSpace вызовом Application.CreateObjectSpace() в отдельных потоках.

Условия возникновения проблемы:

  1. Используется подсистема безопасности Xafari на доменных компонентах (Xafari.Security.DC)
  2. Используется SecurityStrategyComplex
  3. Используются длительные операции, в коде которых создаются новые ObjectSpace

Причина возникновения проблемы.

  1. Xafari содержит контроллер Xafari.Security.Controllers.ActionOperationApplyWindowController, который перед выполнением каждого действия вызывает метод SecuritySystem.ReloadPermissions(). Этот метод по сути выполняет перезагрузку объекта текущего пользователя в SecuritySystem.LogonObjectSpace
  2. Каждый раз при создании нового ObjectSpace вызовом Application.CreateObjectSpace() XAF обращается к списку разрешений текущего пользователя.

Если эти два события происходят одновременно, что является вероятным при многопоточной работе, возникает конфликт: происходит обращение к объекту текущего пользователя из одного потока, в то время, как объект перезачитывается из БД.

Возможные пути решения.

  1. Отключить механизм автоматической перезагрузки разрешений перед выполнением Actions. Для этого в секцию appSettings конфигурационного приложения необходимо добавить ключ ForceActionExecutingPermissionCheck со значением False:

<appSettings>

<add key="ForceActionExecutingPermissionCheck" value="False" />
Механизм автоматической перезагрузки разрешений в общем случае требуется только во время активного администрирования системы, когда для пользователей меняются разрешения на выполнение действий. Если же настройка разрешений завершена или выполняется очень редко, данный механизм можно отключать.

  1. В любом коде, который выполняется в отдельном потоке, создание новых ObjectSpace выполнять в блоке try/catch и в случае неудачного создания повторить попытку (можно несколько раз). Этот подход требует аккуратного кодирования. Подобных требований можно избежать, если воспользоваться третьим подходом.
  2. В приложении использовать потокобезопасные версии классов SecurityStrategyComplex и SelectDataSecurityProvider, код которых приведен ниже.

Класс ThreadSafeSecurityStrategyComplex используется вместо стандартного SecurityStrategyComplex:

Класс ThreadSafeSelectDataSecurityProvider используется при создании SecuredObjectSpaceProvider.
Пример для случая, когда ObjectSpaceProvider создается в классе приложения:

Пример для случая, когда ObjectSpaceProvider создается в обработчике события CreateCustomObjectSpaceProvider (например, в AppModule):