1

マルチスレッド アプリケーション (ASP.NET MVC) では、Web.Config から取得した定数と値を含むグローバル設定クラスが必要です。

このクラスをシングルトンとして静的にしたい...そしてロックされた?

public static class Settings {

  public static LoggerSettings Logger;
  public static MailerSettings Mailer;

  public class LoggerSettings {
    public String Levels { get { return ConfigurationManager.AppSettings["Logger.Levels"]; } }
    public const String Report = "team@xyz.com";
  } // LoggerSettings

  public class MailerSettings {
    public String Contact { get { return ConfigurationManager.AppSettings["Mailer.Contact"]; } }
  } // MailerSettings

}

ダブルロックを実装する必要があると思いますか?いいえ?

これを行う最善の方法がわかりません。助けてもらえますか?

ありがとう、ミゲル

4

5 に答える 5

10

シングルトンとして、このクラスを静的にしたい

C# でシングルトンを正しく実装するには、何が機能し、何が機能しないかについての Jon Skeet の優れた要約を参照してください。

http://csharpindepth.com/Articles/General/Singleton.aspx

ダブルロックを実装する必要があると思いますか?いいえ?

いいえ。ダブルチェック ロックは低ロック技術であるため、メモリが弱いモデルのハードウェアでは非常に危険です。「祝福された」パターンから少しでも逸脱した瞬間、プログラムが予測どおりに動作するというすべての希望を放棄したことになります。

二重チェックのロックを使用する唯一の状況は、次のすべてが当てはまる場合です。

  • シングルチェックロックがパフォーマンスを低下させるという広範な経験的証拠はありますか?
  • 単一チェックのパフォーマンスが受け入れられないとしましょう。単一チェックのロックでは通常、競合が原因でパフォーマンスが低下するため、ステップ 1 で競合を排除します。競合を解消し、許容できるパフォーマンスを得ることができますか? 競合を取り除くことが不可能な場合、または競合していないロックを取得するのに数ナノ秒かかることが原因でパフォーマンスの問題が発生した場合にのみ、ダブルチェック ロックを使用します。後者の場合: うわー、それはそれらのナノ秒が最も遅いものであるという高速なプログラムです
  • 単一チェックのパフォーマンスは受け入れられず、修正できないと仮定しましょう。Interlocked.CompareExchange を使用する、またはLazy<T>許容できるパフォーマンスを持つ別のローロック手法はありますか? 少なくとも、CompareExchangeLazy<T>は専門家によって作成され、すべてのハードウェアに適切にメモリ バリアを適用することを知っています。より優れたツールが既に実装されている場合は、ダブルチェック ロックを使用しないでください。
  • これらのツールのどれも許容できるパフォーマンスを提供しないと仮定しましょう。 ダブルチェックされたロックは許容できるパフォーマンスを提供しますか? そうでない場合は使用しないでください
于 2013-03-28T15:11:24.967 に答える
5

ご覧のとおり、データを読み取るだけです。したがって、ここで IMO をロックする必要はありません。Report などの変数を初期化するには、静的コンストラクターを使用します (これも静的にします)。

于 2013-03-28T13:03:40.907 に答える
1

静的でシングルトンが好きな場合は、次の方法で試してください。

public static class Settings {
  private static readonly object LockObject = new object();
  private static LoggerSetting LoggerInstance;

  public static LoggerSetting LoggerSettings {
    get {
      lock (LockObject) {
         if (LoggerInstance == null)
           LoggerInstance = new LoggerInstance(); 

         return LoggerInstance;
       }
     }
   }

   public class LoggerSetting {
     public String Levels {
       get { return ConfigurationManager.AppSettings["Logger.Levels"]; }
     } 

     public const String Report = "team@xyz.com";
   }
}

そしてそれを次のように使用します:

string x = Settings.LoggerSEttings.Report;
于 2013-03-28T13:24:29.353 に答える
1

Jon Skeet の記事、Implementing the Singleton Pattern in C# をご覧ください。

最も単純で十分なオプション:

public sealed class Settings
{
    private static readonly Settings instance = new Settings();

    public LoggerSettings Logger { get; private set; }
    public MailerSettings Mailer { get; private set; }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Settings()
    {
    }

    private Settings()
    {
       Logger = new LoggerSettings();
       Mailer = new MailerSettings();
    }

    public static Settings Instance { get { return instance;} }
}

public class LoggerSettings {

    public LoggerSettings()
    {
        Levels = ConfigurationManager.AppSettings["Logger.Levels"];
    }

    public String Levels { get; private set; }
    public const String Report = "team@xyz.com";

}

// Mailer settings would look similar

このインスタンスからデータを読み取るだけなので、ロックは必要ありません。シングルトン インスタンスは、他のスレッドがアクセスできるようになる前に作成されるため、そこでもロックする必要はありません。

使用法:

 Settings.Instance.Mailer.Contact
于 2013-03-28T15:54:07.483 に答える
-1

それでも先に進み、シングルトン インスタンスが必要な場合

    public class MySettings{
    private static Object lockObj = new Object();
    private MySettings() {} // private .ctor

    private static MySettings _instance;

    public static MySettings MySingleSettings{
     get{
      if(_instance == null){
      lock(lockObj){
        if(_instance == null)
          _instance = new MySettings();
        }
      }
       return _instance;
    }
}
于 2013-03-28T13:10:02.990 に答える