2013-08-09 20 views
5

Mam metodę, która może być wywołana z wielu wątków, ale chcę tylko, aby pierwszy wątek zrobił jakąś logikę wewnątrz metody. Tak więc planuję użyć zmiennej boolean. Pierwszy wątek, który wchodzi, ustawi zmienną boolowską na false (aby zapobiec przedostaniu się kolejnych wątków) i wykona logikę metody.jak zablokować zawartość metody

Kolejne wątki, które przychodzą do tej metody, sprawdzi zmienną boolean. Ponieważ została ustawiona na wartość false przez pierwszy wątek, pominą one logikę metody.

W kodzie, coś takiego:

private void myMethod() 
{ 
    if (firsTime) //set to true in the constructor 
    { 
     firstTime = false; //To prevent other thread to come inside here. 
     //method logic 
    } 
} 

chcę użyć blokady, aby wykonać to, ale nie wiem, gdzie go umieścić.

Jeśli zablokuję wewnątrz "if", aby zmienić firstTime na false, jego możliwe 2 lub więcej wątków już wchodzą do wnętrza if (nie chcę tego).

Jeśli zablokować poza "if", aby zmienić firstTime na false, w jaki sposób pierwszy wątek może wejść do wewnątrz, jeśli wykonać logikę metody, jeśli firstTime jest już ustawione na false?

Moje pytanie brzmi: jak wykonać blokadę, aby uzyskać pożądaną funkcjonalność? (Pierwszy wątek, który przychodzi, ustawia logikę metody boolean i execute).

Nie mogę zablokować całej logiki metody, ponieważ będzie to bardzo czasochłonne operacje.

+0

chciałbym po prostu zadzwoń logikę metoda w ctor, ale może to tylko ja :) –

Odpowiedz

7

Można użyć Interlocked.Exchange aby rozwiązać ten problem. Ustawi wartość danej zmiennej na określoną wartość i zwróci wartość, która była wcześniej w zmiennej, i zrobi to wszystko atomowo. Rozwiązanie to zapewnia, że ​​tylko jeden wątek zostanie kiedykolwiek uruchomić kod w if:

private static int isFirst = 1; 
public static void Foo() 
{ 
    if (Interlocked.Exchange(ref isFirst, 0) == 1) 
    { 
     //DoStuff 
    } 
} 

Zauważ, że Interlocked.Exchange ma przeciążenie, że trwa bool, dlatego jesteś zmuszony do korzystania z int (lub jakiś inny type) zamiast, używając 1 dla true i 0 dla false.

Jeśli chcesz rozwiązanie korzystając lock, zamiast Interlocked, można to zrobić poprzez zastosowanie dodatkowego lokalnego bool wartość:

private static bool isFirst = true; 
private static object key = new object(); 
public static void Foo() 
{ 
    bool amFirst; 
    lock (key) 
    { 
     amFirst = isFirst; 
     isFirst = false; 
    } 

    if (amFirst) 
    { 
     //DoStuff 
    } 
} 
+0

Dzięki. To jest rozwiązanie dla mnie :) – user2232787

+0

Myślę, że chciałbym przeformułować "Jeśli chcesz rozwiązanie za pomocą' blokady' ... "do" Jeśli * naprawdę źle * chcesz rozwiązanie za pomocą 'blokady' ..." - Sposób "interlocked" jest znacznie łatwiejszy do naśladowania. –

+0

@retailcoder Najpierw wstawiam rozwiązanie "Interlocked", ale co do tego, które jest preferowane, jest w większości subiektywne. Chciałbym, aby rozwiązanie "Interlocked" było znacznie lepsze, gdyby można było użyć 'bool'; bycie zmuszonym do użycia int jako 'bool' trochę osłabia jego czytelność. – Servy

-3

Widocznie, C# ma natywną oświadczenie dla tego: oświadczenie blokada

http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

+1

Nie jesteś pomocny. Najwyraźniej wie, co oznacza blokada. On pyta, gdzie go umieścić. – ShadowCat7

+0

Ach, przepraszam, mój zły - nie przeczytałem poprawnie jego pytania, ponieważ sam nie wiedziałem, że C# ma Lock-oświadczenie :-) –

+0

Możesz zdobyć sobie znaczek, usuwając ten wpis :) –

Powiązane problemy