2012-10-26 14 views
5

Następujący blok kodu, preformy ładowanie obiektu w C#.Preformowanie bloku kodu tylko raz

public bool IsModelLoaded { get; set; } 
public override MyObject Load() 
    { 
     if (!IsModelLoaded) 
     { 
      Model = MyService.LoadMyObject(Model); 
      IsModelLoaded = true; 
     } 
     return Model; 
    } 

Moim zamiarem jest uruchomienie tego bloku tylko raz, a zatem ładowanie modelu tylko raz. Mimo to ten blok kodu działa dwukrotnie z 2 różnych wątków.

Jak mogę się upewnić, że ten blok działa tylko raz? (na multiplethreads).

Dziękuję.

Odpowiedz

3

Najprostszy byłoby dodać

[MethodImpl(MethodImplOptions.Synchronized)] 
public override MyObject Load() 
{ 
    //snip 
} 

ale należy pamiętać, to stawia blokadę całego obiektu, a nie tylko metody. Niezbyt dobra praktyka.

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx

synchroniczny

określa, że ​​metoda ta może być wykonywana przez tylko jedną nić w czasie. Metody statyczne blokują typ, a metody instancji blokują instancję. W dowolnej funkcji instancji może być wykonywany tylko jeden wątek i tylko jeden wątek może być wykonywany w dowolnej funkcji statycznej klasy.

0

Tworzenie statycznej obiektu (jak Boolean), która określa, czy kod został ran lub nie umieszczając go w if :)

EDIT: Nie jestem pewien, czy to threadsafe, więc to może nie jest rozwiązaniem dla ciebie.

2

Użyj Lazy<T> Class:

private readonly Lazy<MyObject> myObject; 

public MyClass() 
{ 
    myObject = new Lazy<MyObject>(() => 
    { 
     return MyService.LoadMyObject(); 
    }, LazyThreadSafetyMode.ExecutionAndPublication); 
} 

public bool IsModelLoaded 
{ 
    get { return myObject.IsValueCreated; } 
} 

public override MyObject Load() 
{ 
    return myObject.Value; 
} 
1

I starają się realizować singleton wzór. Ale twoja wersja nie jest bezpieczna dla wątków. Czytaj więcej tutaj: http://www.dofactory.com/Patterns/PatternSingleton.aspx. Spróbuj skorzystać z tej realizacji:

public sealed class Singleton 
{ 
    static Singleton instance=null; 
    static readonly object padlock = new object(); 

    Singleton() 
    { 
    } 

    public static Singleton Instance 
    { 
     get 
     { 
      lock (padlock) 
      { 
       if (instance==null) 
       { 
        instance = new Singleton(); 
       } 
       return instance; 
      } 
     } 
    } 
} 
1
Action myCodeBlock =()=> 
{ 
    //do your job 
    //... 
    myCodeBlock =()=>{}; 
} 

Po wywołaniu myCodeBlock() raz zostanie ona przepisana przez metody, która nic nie robi. Nadal musisz się upewnić, że ta metoda jest bezpieczna - użyj lock lub cokolwiek innego.

1

Jeśli chcesz pisać bezpieczny kod nici i upewnij się, że blok działa tylko raz, można napisać tak:

private System.Object lockThis = new System.Object(); 
public override MyObject Load() 
{ 
    lock (lockThis) { 
     if (!IsModelLoaded) 
     { 
      Model = MyService.LoadMyObject(Model); 
      IsModelLoaded = true; 
     } 
    } 
    return Model; 
}