2010-06-15 4 views
2

Рассмотрим следующий фрагмент кода:Являются ли статические делегаты потокобезопасными?

public static class ApplicationContext 
{ 
    private static Func<TService> Uninitialized<TService>() 
    { 
     throw new InvalidOperationException(); 
    } 

    public static Func<IAuthenticationProvider> AuthenticationProvider = Uninitialized<IAuthenticationProvider>(); 
    public static Func<IUnitOfWorkFactory> UnitOfWorkFactory = Uninitialized<IUnitOfWorkFactory>(); 
} 

//can also be in global.asax if used in a web app. 
public static void Main(string[] args) 
{ 
    ApplicationContext.AuthenticationProvider =() => new LdapAuthenticationProvider(); 
    ApplicationContext.UnitOfWorkFactory =() => new EFUnitOfWorkFactory(); 
} 

//somewhere in the code.. say an ASP.NET MVC controller 
ApplicationContext.AuthenticationProvider().SignIn(username, true); 

, делегированных в статическом классе ApplicationContext потокобезопасного в том смысле, что множественные-потоки могут ссылаться на них?

С какими потенциальными проблемами я столкнусь, если я продолжу этот подход?

+0

Пожалуйста, объясните больше, что вы подразумеваете под статическим делегатом. – leppie

+0

@leppie В примере кода переменная static Func AuthenticationProvider является статическим делегатом. – leypascua

ответ

3

ли делегаты в статическом классе ApplicationContext потокобезопасной в смысле, что множественные-потоки могут вызывать их?

Да. Но делегат только как потокобезопасный, как метод, на который он указывает.

Итак, если методы, вызванные вашими делегатами AuthenticationProvider и UnitOfWorkFactory, являются потокобезопасными, тогда ваши делегаты будут.

В коде, который вы предоставили, это просто вызовы конструктора. На самом деле это не так много потокобезопасности (если у вас нет сумасшедшей логики потоков в ваших конструкторах - я, конечно, надеюсь, что нет).

Какие потенциальные проблемы я столкнусь, если Я преследую этот подход?

Отсутствует результат, вызванный вызовом ваших делегатов. Опять же, единственная проблема, связанная с безопасностью потоков, которую вы должны волновать, - это те, которые относятся к фактическим методам, называемым вашими делегатами (в этом случае конструкторы для LdapAuthenticationProvider и EFUnitOfWorkFactory).

UPDATE: limpalex сделал хорошее наблюдение: в коде, вы в курсе, вы на самом деле вызоваUninitialized<TService> метод в статическом конструкторе для вашего ApplicationContext класса, который будет бросать исключение. То, что вы хотите сделать, это назначить вашим делегатам. Я думаю, что вы собираетесь что-то вроде этого:

// note: changed return type to TService to match Func<TService> signature 
private static TService Uninitialized<TService>() 
{ 
    throw new InvalidOperationException(); 
} 

// note: removed() symbols to perform assignment instead of method call 
public static Func<IAuthenticationProvider> AuthenticationProvider = Uninitialized<IAuthenticationProvider>; 
public static Func<IUnitOfWorkFactory> UnitOfWorkFactory = Uninitialized<IUnitOfWorkFactory>; 
2

Ваша функция Uninitialized() не возвращает объект Func, который генерирует исключение, он просто бросает исключение. Причина, по которой это произойдет в статическом конструкторе ApplicationContext, этот тип станет непригодным. Вы должны сделать что-то подобное: return() => throw new IOE(); "

+0

Хорошая добыча! Большое спасибо! – leypascua

+0

Хорошая находка. Пропустил это сам. –

Смежные вопросы