2010-06-15 58 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 2010-06-15 07:29:51

+0

@leppie在代碼示例中,變量static Func AuthenticationProvider是一個靜態委託。 – leypascua 2010-06-15 07:32:37

回答

3

在靜態類代表 ApplicationContext的線程安全的 意義上的多線程可以調用 呢?

是的。但是,委託只與它指向的方法一樣安全。

因此,如果您的AuthenticationProviderUnitOfWorkFactory調用的方法是線程安全的,那麼您的代表也是如此。

在您提供的代碼中,這些只是構造函數調用。它並沒有比這更好的線程安全性(除非你在構造函數中有一些瘋狂的線程邏輯 - 我當然希望沒有)。

我會面臨哪些潛在的問題 我追求這種方法嗎?

沒有直接來自調用您的代表的結果。同樣,關於線程安全的唯一問題您應該擔心的是那些與您的代表調用的實際方法有關的問題(在這種情況下,LdapAuthenticationProviderEFUnitOfWorkFactory的構造函數)。

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

你未初始化()函數不返回拋出異常函數求對象,它只是拋出一個異常。 因爲這會發生在ApplicationContext靜態構造函數中,所以這種類型將變得不可用。 你應該這樣做:「return()=>拋出新的IOE();」

+0

好抓!非常感謝! – leypascua 2010-06-15 07:39:30

+0

很好找。錯過了那一個人。 – 2010-06-15 07:44:45