2013-01-08 10 views
10

将来的に私のウェブサイトがクラウド上でホストされ、多くの要求を処理できるようにしたいと考えています。ASP.NET MVC静的変数の安全性

静的変数はどれくらい安全ですか?

別々のユーザーによる別々のリクエストが実際にこれらの静的変数を共有しているため、それらは安全ではありませんか?それとも、スレッド/シャーディングなどのサイトを広げて(高負荷を処理するために)スレッドが静的変数を共有しているからですか?

主に静的プロパティを持つヘルパークラスがありますが、代わりに各クラスのインスタンスを作成してインスタンスにアクセスするようにこのアーキテクチャを変更する必要がありますか?

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メソッドを複数のスレッドから同時に呼び出そうとすると、コードが非常にひどくクラッシュする可能性があります。一方、このOnAppInit静的メソッドをApplication_Startイベント(1つのスレッドから1回だけ実行されることが保証されています)内に1回だけ呼び出す場合は、そこで使用するのがかなり安全です。

これは、静的変数とメソッドは一般的にアプリケーションでは悪い考えであると言っています。それらを適切に使用する方法がわからない場合や、同時スレッドから実行する必要がある場合にアクセスを同期する方法がわからない場合は、悪い考えです。スレッドセーフなコードを書くことは非常に難しい問題であり、ASP.NETアプリケーションなどのマルチスレッドアプリケーションを作成するときにはどうしたらいいのですか? ASP.NETアプリケーションで、このための十分に確立された場所を使用します。

  • バックエンド(例えば、リレーショナルデータベースすることができる)
  • アプリケーション状態
  • キャッシュ
  • HTTPコンテキスト状態
  • セッション状態
  • クライアントクッキー

これらの場所は具体的ですASP.NETアプリケーションに状態を格納するように設計されています(もちろん、最初のものを除いて、あらゆる種類のアプリケーションで使用できます)。

+0

もう少し説明できますか?「複数のスレッドから同時にOnAppInitメソッドを呼び出そうとすると、あなたのコードが非常にひどくクラッシュする可能性がありますか?正確にこの方法で間違っていたことは何ですか? – Dmitry

+3

このメソッドは、辞書型のローカル静的変数を変更しています。私の答えで言ったように、このタイプは**スレッドセーフではありません**。たとえば、最初のスレッドは辞書にある値を割り当て、別のスレッドが最初にスレッドが保存した可能性のあるすべての値を失う新しい辞書に単に割り当てます。このコードは、複数のスレッドから決して呼び出されるべきではありません。 –

+0

もう一度ありがとうダーリン!次に、私は簡単にアクセスできるようにグローバルオブジェクトに作成するインスタンスを格納するか、唯一のインスタンスを返す各クラスに静的なGet()メソッドを用意します。それはそれを修正する必要があります。 :) – Baconbeastnz

2

を静的変数が要求間で共有されます。ここでは

例えば、私がやっているもののサンプルです。 さらに、アプリケーションが起動すると、 が初期化されるため、AppDomain、つまりアプリケーションが再起動されると、その値が再初期化されます。

関連する問題