2014-09-19 6 views
0

У меня возникли проблемы с пониманием основных концепций блокировки в многопользовательском/веб-приложении. Когда пользователь получает разрешения нашей федерации, он вернется с иском имя пользователя, который мы будем использовать то, чтобы получить некоторую дополнительную информацию о нем, как так:Нужна помощь в понимании блокировки в ASP.NET

var claimsIdentity = (ClaimsIdentity)HttpContext.Current.User.Identity; 
if(!claimsIdentity.HasClaim(CustomClaims.UserId)) //If not set, retrieve it from dataBase 
{ 
    //This can take some time 
    var userId = retrieveUserId(claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)); 
    //Because the previous call could take some time, it's possible we add the claim multiple time during concurrent requests 
    claimsIdentity.AddClaim(new Claim(CustomClaims.UserId, userId)); 
} 

Как указано в коде, имея дубликат претензии не совсем то, что я ищу, так что я думал, что запереть все вокруг проверить, существует ли требование или нет:

private static readonly object _authorizeLock = new object(); 
... 
lock(_authorizeLock) 
{ 
    if(!claimsIdentity.HasClaim(CustomClaims.UserId)) //If not set, retrieve it from dataBase 
    { 
     ... 
    } 
} 

Однако это не так. Не будет ли эта блокировка для всего входящих запросов? Это означало бы, что даже авторизованным пользователям все равно придется «ждать», хотя их информация уже была восстановлена.

Есть ли у кого-нибудь идеи, как я мог бы с этим справиться?

+0

Вы право быть подозрительным. Замки следует избегать в веб-приложении. Вероятно, вам нужно решение с высокой доступностью, которое обычно означает несколько IIS. Эта блокировка не распространяется на кластер. – usr

+0

http://msdn.microsoft.com/en-gb/library/c5kehkcz.aspx kinda говорит все это ... »Ключевое слово lock гарантирует, что один поток не войдет в критический раздел кода, а другой поток находится в критическом Если другой поток пытается ввести заблокированный код, он будет ждать, блокировать, пока объект не будет выпущен. " Это зависит от того, где вы ставите чек, если вы сделали это на каждой загрузке страницы, то да, это затронет всех пользователей для всех запросов. Реальный вопрос здесь в том, почему вы блокируете не только «так что я думал, что я заблокирую все», чего вы пытаетесь достичь? –

+0

Вот чего я боялся ... Есть ли приличные решения для этого, кроме блокировки? @PaulZahra Я не уверен, что я понимаю вопрос в вашем редактировании. – Kippie

ответ

0

Ответ 1: Пройдитесь и повторяйте записи.

Ответ 2: Если у вас сеансы включены, вы получаете неявное блокирование между запросами одного и того же пользователя (сеанса), обращаясь к хранилищу сеансов. Просто добавьте фиктивный

Session["TRIGGER_SESSION_LOCKING_DUMMY"] = true 

Ответ 3: Реализовать некоторые пользовательские блокировки на объекте индексируется вашей идентичности. Что-то вроде этого

lock(threadSafeStaticDictionary[User.Identity.Name]) { ... } 

Ответ 4: блокировки на объекте идентичности непосредственно (который должен быть общим, так как вы получаете дубликаты) (хотя это не рекомендуется)

lock(User.Identity) 
Смежные вопросы