2009-09-07 8 views
8

Zastanawiam się tylko, czy ten kod, który inny programista (który odszedł) jest OK, myślę, że chciał uniknąć blokady. Czy istnieje różnica w wydajności między tym a zwykłym blokowaniem?Blokowane używane do zwiększania/naśladowania wartości logicznej, czy jest to bezpieczne?

private long m_LayoutSuspended = 0; 
    public void SuspendLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 1); 
    } 

    public void ResumeLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 0); 
    } 

    public bool IsLayoutSuspended 
    { 
     get { return Interlocked.Read(ref m_LayoutSuspended) != 1; } 
    } 

Myślałem, że coś takiego będzie łatwiejsze z zamkiem? Będzie on rzeczywiście używany przez wiele wątków, dlatego też zdecydowano o użyciu blokowania/blokowania.

Odpowiedz

8

Osobiście używam lotny Boolean:

private volatile bool m_LayoutSuspended = false; 
public void SuspendLayout() 
{ 
    m_LayoutSuspended = true; 
} 

public void ResumeLayout() 
{ 
    m_LayoutSuspended = false; 
} 

public bool IsLayoutSuspended 
{ 
    get { return m_LayoutSuspended; } 
} 

Potem znowu, jak już przyznał ostatnio w innym miejscu, lotny nie znaczy zupełnie co myślałem, że to zrobił. Podejrzewam, że to jest w porządku :)

Nawet jeśli pozostaniesz przy Interlocked, zamieniłbym go na int ... nie ma potrzeby, aby 32-bitowe systemy mogły mieć problemy z utworzeniem 64-bitowego zapisu, gdy mogą to łatwo zrobić z 32 bitów ...

+0

@Jon: Jestem ciekawa, czy możesz rozwinąć "niestabilność, nie oznacza całkiem, co myślałem, że to zrobiło"? – LukeH

+0

@Luke: Planuję szczegółowo omówić go w poście na blogu, ale większość z nich to http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx. –

+0

Dla podkreślenia, niestabilna długość nie byłaby ** bezpieczna (w systemie 32-bitowym). –

13

Tak co robisz jest bezpieczne z punktu widzenia rasy sięga pole m_LayoutSuspended jednak blokada jest wymagana z następującego powodu jeśli kod wykonuje następujące operacje:

if (!o.IsLayoutSuspended) // This is not thread Safe ..... 
{ 
    o.SuspendLayout(); // This is not thread Safe, because there's a difference between the checck and the actual write of the variable a race might occur. 
    ... 
    o.ResumeLayout(); 
} 

Bezpieczniejszy sposób, który używa CompareExchange, aby upewnić się, że nie ma wyścigu warunki wystąpiły:

private long m_LayoutSuspended = 0; 
public bool SuspendLayout() 
{ 
    return Interlocked.CompareExchange(ref m_LayoutSuspended, 1) == 0; 
} 

if (o.SuspendLayout()) 
{ 
    .... 
    o.ResumeLayout(); 
} 

Albo jeszcze lepiej po prostu użyj zamka.

+0

[Interlocked.CompareExchange nie ma przeciążenia z dwoma argumentami ] (https://msdn.microsoft.com/en-us/library/system.threading.interlocked (v = vs.110) .aspx) może twój wiersz powinien przeczytać 'return Interlocked.CompareExchange (ref m_LayoutSuspended, 1, 0) == 0; ' –

+0

Został mi również wskazany (https://meta.stackoverflow.com/questions/320996/changed-edit-still-doesnt-compile#comment333601_320996), który zmienia go na' return Interlocked.Exchange (ref m_LayoutSuspended, 1) == 0; 'również załatwi sprawę. –

Powiązane problemy