Używanie instrukcji lock w pętli w C #

Weźmy przykładową klasę SomeThread, w której próbujemy uniemożliwić wywoływanie metod DoSomething po ustawieniu właściwości Running na false, a Dispose jest wywoływane przez klasę OtherThread, ponieważ jeśli zostaną wywołane po metodzie Dispose, świat skończy się, gdy znać to.

Wydaje się, że z powodu pętli istnieje szansa na coś złego. Że w momencie, w którym rozpoczyna następną pętlę i przed wykonaniem blokady przed wywołaniem metod DoSomething, Uruchomienie może zostać zmienione na false, a Disposed wywołane zanim trafi w zamek. W tym scenariuszu życie nie byłoby dobre.

Szukałem sposobów, aby sobie z tym poradzić, używając pętli w prostej, łatwej do utrzymania metodzie. Dla rekordu wziąłem pod uwagę wzorzec sprawdzania podwójnej blokady, jednak wydaje się, że nie jest on zalecany dla C #.

Ostrzeżenie: Jest to uproszczony przykład, aby ułatwić skupienie się na problemie z pętlą i blokowaniem w jednym. Jeśli nie opracowałem wystarczająco miejsca, daj mi znać, a zrobię wszystko, co w mojej mocy, aby wypełnić wszelkie szczegóły.

public class SomeThread : IDisposable
{
    private object locker = new object();
    private bool running = false;

    public bool Running 
    { 
        get
        {
            lock(locker)
            {
                return running;
            }
        }
        set
        {
            lock(locker)
            {
                running = value;
            }
        }
    }

    public void Run()
    {
        while (Running)
        {
            lock(locker)
            {
                DoSomething1();
                DoSomething2();
            }
        }
    }

    private void DoSomething1()
    {
        // something awesome happens here
    }

    private void DoSomething2()
    {
        // something more awesome happens here
    }

    public void Dispose()
    {
        lock (locker)
        {   
            Dispose1();
            Dispose2();
        }
    }

    private void Dispose1()
    {
        // something awesome happens here
    }

    private void Dispose2()
    {
        // something more awesome happens here
    }

}

public class OtherThread
{
    SomeThread st = new SomeThread();

    public void OnQuit()
    {
        st.Running = false;
        st.Dispose();

        Exit();
    }
}

questionAnswers(3)

yourAnswerToTheQuestion