문제

즉,이는 단일 구현을 쓰레드에 안전하:

public class Singleton
{
    private static Singleton instance;

    private Singleton() { }

    static Singleton()
    {
        instance = new Singleton();
    }

    public static Singleton Instance
    {
        get { return instance; }
    }
}
도움이 되었습니까?

해결책

Static 생성자를 보장하는 것만 실행하면 응용 프로그램당 도메인 전에,모든 클래스의 인스턴스를 만들거나 어떤 정적 멤버에 액세스할 수 있습니다. http://msdn.microsoft.com/en-us/library/aa645612.aspx

구현은 다음과 같은 스레드에 안전에 대한 초기의 건축,즉,잠금 또는 null 테스트에 필요한을 구성하는 단일 객체입니다.그러나,이 의미하지 않는 어떤 사용하의 인스턴스에 동기화됩니다.거기에 다양한 방법으로 이를 수행할 수 있습니다;나는 다음과 같습니다.

public class Singleton
{
    private static Singleton instance;
    // Added a static mutex for synchronising use of instance.
    private static System.Threading.Mutex mutex;
    private Singleton() { }
    static Singleton()
    {
        instance = new Singleton();
        mutex = new System.Threading.Mutex();
    }

    public static Singleton Acquire()
    {
        mutex.WaitOne();
        return instance;
    }

    // Each call to Acquire() requires a call to Release()
    public static void Release()
    {
        mutex.ReleaseMutex();
    }
}

다른 팁

이 모든 답변을 제공 같은 일반적인 답변,거기에 하나의 실행할 수 있습니다.

을 기억하는 모든 잠재적인 파생어의 일반적인 클래스로 컴파일되는 개인 형식입니다.그래서 주의 사용을 구현하는 경우 정적 생성자에 대한 일반적인 형식입니다.

class MyObject<T>
{
    static MyObject() 
    {
       //this code will get executed for each T.
    }
}

편집:

여기에서 데모입니다:

static void Main(string[] args)
{
    var obj = new Foo<object>();
    var obj2 = new Foo<string>();
}

public class Foo<T>
{
    static Foo()
    {
         System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));        
    }
}

콘솔에서:

Hit System.Object
Hit System.String

를 사용하여 정적 생성자를 실제로 면.Static 생성자를 실행됩니다.

C#어 사양 http://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx:

Static 생성자를 위한 클래스를 실행합에서 가장 번에 지정된 응용 프로그램 도메인에 있습니다.의 실행에 정적 생성자에 의해 트리거의 첫 번째 다음과 같은 이벤트가 발생하는 응용 프로그램 내에 도메인:

  • 클래스의 인스턴스를 만듭니다.
  • 모든 정의 멤버 클래스를 참조됩니다.

그래서 신뢰할 수 있는 단일 것이 올바르게 인스턴스화됩니다.

Zooba 한 모든 지점(15 초 내 앞에,너무!) 는 정적 생성자를 보증하지 않습니다 thread-safe 공유 액세스를 단일.는 것이 처리해야 하에서 다른 방식이다.

여기에 Cliffnotes 버전에서 위 MSDN 페이지에서는 c#단일:

를 사용하여 다음과 같은 패턴을 만들어,당신은 잘못 될 수 없:

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

   private Singleton(){}

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

저희는 단일 기능을 제공,당신은이 두 가지에 대한 무료(에 대해서는 싱글에서는 c++):

  1. lazy 건설(또는 건설하는 경우 그것은 결코 이라고)
  2. 동기화

Static 생성자를 보장하는 불만 일단 당 응용 프로그램 도메인의 접근을 확인해야합니다.그러나,그것이 기능적으로 다르에서 더 많은 간결하고,인라인 버전:

private static readonly Singleton instance = new Singleton();

스레드에 안전이 문제가 더 있을 때 느리게 초기화하는 것들입니다.

일반적인 언어는 인프라 사양 는 보장은"형식 이니셜라이저를 실행하여 정확하게 위해 한 번에 지정된 형지 않는 한 명시적으로 호출하여 사용자 코드입니다." (섹션 9.5.3.1.) 그렇지 않으면 당신은 어떤 외 IL 에 느슨한 호출하는 단일::.cctor 직접적으로(가)정적 생성자를 것입니다 정확히 실행하기 전에 한 번에 단일 형식을 사용하는 단 하나의 인스턴스의 단일 창조될 것이고 귀하의 인스턴스의 속성은 스레드에 안전합니다.

한 경우에는 단일의 생성자를 인스턴스에 액세스하산(조 간접적으로)다음의 인스턴스 숙박 시설은 null 입니다.최고 당신이 할 수 있는 감지하는 경우 이런 예외를 확인하여 해당 인스턴스가 null 이 아닌지에서 속성 접근.후에 정적 생성자를 완료한 인스턴스를 제공하지 않는 것입니다 null 입니다.

Zoomba 의 응답 지 확인 해야 하는 단일 안에 액세스하에서 여러 스레드 또는 구현 잠금 메커니즘을 사용하여 주위의 싱글턴 인스턴스입니다.

Static 생성자 완료 실행 모든 쓰레드에 액세스할 수 있다.

    private class InitializerTest
    {
        static private int _x;
        static public string Status()
        {
            return "_x = " + _x;
        }
        static InitializerTest()
        {
            System.Diagnostics.Debug.WriteLine("InitializerTest() starting.");
            _x = 1;
            Thread.Sleep(3000);
            _x = 2;
            System.Diagnostics.Debug.WriteLine("InitializerTest() finished.");
        }
    }

    private void ClassInitializerInThread()
    {
        System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() starting.");
        string status = InitializerTest.Status();
        System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() status = " + status);
    }

    private void classInitializerButton_Click(object sender, EventArgs e)
    {
        new Thread(ClassInitializerInThread).Start();
        new Thread(ClassInitializerInThread).Start();
        new Thread(ClassInitializerInThread).Start();
    }

위의 코드를 생성한 결과다.

10: ClassInitializerInThread() starting.
11: ClassInitializerInThread() starting.
12: ClassInitializerInThread() starting.
InitializerTest() starting.
InitializerTest() finished.
11: ClassInitializerInThread() status = _x = 2
The thread 0x2650 has exited with code 0 (0x0).
10: ClassInitializerInThread() status = _x = 2
The thread 0x1f50 has exited with code 0 (0x0).
12: ClassInitializerInThread() status = _x = 2
The thread 0x73c has exited with code 0 (0x0).

도 static 생성자의 시간을 실행하고,다른 스레드를 멈추고 기다렸습니다.모든 쓰레드의 값을 읽어 _x 세트의 맨 아래에서 정적 생성자입니다.

그냥 현학적,그러나 같은 것은 없으로 정적인 생성자이지만,오히려 정체되 이니셜라이저 유형, 여기에 작은 모의 순환적인 정적 생성자를 종속성을 보여줍니다 이 점이다.

정적 생성자를 보장할 스레드에 안전합니다.또한 토론에서는 싱글에 DeveloperZen:http://www.developerzen.com/2007/07/15/whats-wrong-with-this-code-1-discussion/

지만 다른 답변은 주로 정확한 있는 또 다른 경고 정전기와 생성자입니다.

당 섹션 II.10.5.3.3 인종 및 교착 상태ECMA-335Common Language 인프라

유형을 초기화하지 아니하며 혼자 교착 상태를 만들지 않으면 일부 코드 라는 형식의 이니셜라이저(직접적 또는 간접적으로)명시적으로 를 호출을 차단 작업입니다.

다음 코드에서는 교착 상태

using System.Threading;
class MyClass
{
    static void Main() { /* Won’t run... the static constructor deadlocks */  }

    static MyClass()
    {
        Thread thread = new Thread(arg => { });
        thread.Start();
        thread.Join();
    }
}

원래 저자가 이고르,제작,자신의 게시물 .

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top