2013-01-08 61 views
10

我想確保我的網站能夠在將來託管在雲上,並且它可以處理很多請求。ASP.NET MVC靜態變量有多安全

靜態變量有多安全?

它們是不安全的,因爲單獨用戶的不同請求實際上共享這些靜態變量?或者是因爲如果你通過線程/分片或類似的方式傳播站點(處理高負載),這些線程共享靜態變量?

主要是我有助手類,具有靜態屬性,我應該改變這個架構,以便我創建每個類的實例並訪問實例嗎?

E.G下面是我在做什麼的樣本:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using Mvc.Mailer; 

namespace MVCWebsite.Helpers 
{ 
     public class AppSettings 
     { 
       public static void OnAppInit() 
       { 
         //General 
         AppName = "MyApp"; 
         DesktopBaseURLs = new Dictionary<string, string>(); 
         DesktopBaseURLs.Add("dev", "localhost:50560"); 
         DesktopBaseURLs.Add("test", "www.test.whatever.com"); 
         DesktopBaseURLs.Add("live", "www.whatever.com"); 
         MobileBaseURLs = new Dictionary<string, string>(); 
         MobileBaseURLs.Add("dev", "m.local.whatever.com"); 
         MobileBaseURLs.Add("test", "m.test.whatever.com"); 
         MobileBaseURLs.Add("live", "m.whatever.com"); 

         //Emails 
         EmailHostName = AppName + ".com"; //For the moment atleast 
         NoReplyEmailAddress = "[email protected]" + EmailHostName.ToLower(); 
         SupportEmailAddress = "[email protected]" + EmailHostName.ToLower(); 
         ErrorEmailAddress = "[email protected]" + EmailHostName.ToLower(); 

         //Resources 
         TempFileURL = "/content/temp/"; 
         UserDataURL = "/content/user-content/"; 
         ProfilePicturesURL = UserDataURL + "profile-pictures/"; 

         var a = GlobalHelper.GetURLAsServerPath(ProfilePicturesURL); 
         var b = a; 

       } 

       //General 
       public static string AppName { get; set; } 
       public static Dictionary<string, string> DesktopBaseURLs; 
       public static Dictionary<string, string> MobileBaseURLs; 

       //Emails 
       public static string EmailHostName { get; set; } 
       public static string NoReplyEmailAddress { get; set; } 
       public static string SupportEmailAddress { get; set; } 
       public static string ErrorEmailAddress { get; set; } 

       //Resources 
       public static string UserDataURL { get; set; } 
       public static string TempFileURL { get; set; } 
       public static string ProfilePicturesURL { get; set; } 

       //Methods 
       public static void SetAppURL() 
       { 

       } 
     } 
} 
+0

同樣的規則適用...靜態在應用程序域內共享。對於共享的配置數據(如你的例子),這可能正是你想要的,但要注意只從一個線程初始化一次。 –

回答

15

您的代碼不是線程安全的。您正在多個請求之間共享可能由多個線程執行的靜態變量。請記住,您用作基礎存儲的Dictionary<TKey, TValue>類不是線程安全類,這意味着如果您嘗試從多個線程同時調用OnAppInit方法,則代碼可能會崩潰得非常嚴重。另一方面,如果您在Application_Start事件中只調用一次這個OnAppInit靜態方法(這保證只從一個線程運行一次),那麼在那裏使用它是非常安全的。

這就是說靜態變量和方法在應用程序中通常是一個壞主意是不正確的。如果你不知道如何正確使用它們,或者如果你不知道如何同步對它們的訪問,如果你需要在併發線程中完成這些訪問,它們是一個壞主意。編寫線程安全代碼是一個非常困難的主題,如果您擔心錯誤(不會在編寫多線程應用程序(如ASP.NET應用程序)時出錯),不要像這樣共享狀態。使用此的完善的地方在ASP.NET應用程序:

  • 後端(例如可以是一個關係數據庫)
  • 申請國家
  • 緩存
  • HTTP上下文國家
  • 會話狀態
  • 客戶端Cookie

這些地方是特定的lly設計用於在ASP.NET應用程序中存儲狀態(除了可用於任何類型應用程序的第一個功能)。

+0

你能解釋多一點......你是什麼意思「如果你試圖從多個線程同時調用OnAppInit方法,你的代碼可能崩潰得非常糟糕」?這種方法究竟會出錯? – Dmitry

+3

那麼這個方法正在修改一個類型爲Dictionary的局部靜態變量。正如我在我的回答中所說的,這種類型是**不是線程安全的**。因此,例如,第一個線程將爲字典分配一些值,並在另一個線程將其簡單地分配給一個新的字典時,開始爲其添加值,從而丟棄第一個線程迄今可能保存的所有值。永遠不要從多個線程調用此代碼。 –

+0

再次感謝達林!然後,我會將我創建的實例存儲在全局對象中以便輕鬆訪問,或者我將在每個只返回唯一實例的類中使用靜態Get()方法。這應該解決它。 :) – Baconbeastnz

2

靜態變量將請求之間共享。 此外,它們將在應用程序啓動時初始化, 因此,如果AppDomain因此應用程序重新啓動,它們的值將被重新初始化。