Являются ли статические делегаты потокобезопасными? - PullRequest
3 голосов
/ 15 июня 2010

Рассмотрим этот фрагмент кода:

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 поточно-безопасными в том смысле, что их могут вызывать несколько потоков?

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

Ответы [ 2 ]

3 голосов
/ 15 июня 2010

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

Да.Но делегат является настолько же поточно-ориентированным, как и метод, на который он указывает.

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

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

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

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

ОБНОВЛЕНИЕ : 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 голосов
/ 15 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...