在C#中的循环中使用lock语句

时间:2010-01-21 21:59:36

标签: c# loops multithreading locking

让我们尝试使用示例类SomeThread,我们试图在Running属性设置为false并且OtherThread类调用Dispose之后阻止调用DoSomething方法,因为如果在Dispose方法之后调用它们将是世界将我们知道它结束了。

感觉因为循环而有可能发生邪恶的事情。在调用DoSomething方法之前,在启动下一个循环和锁定之前,可以将Running更改为false,并在它到达锁定之前调用Disposed。在这种情况下,生活不会很好。

我正在寻找在简单易于维护的方法中使用循环时处理此问题的方法。为了记录,我确实考虑过Double Lock Check图案,但是它似乎不适合C#。

警告: 这是一个简化示例,旨在让您轻松关注循环和锁定问题。如果我没有详细说明某个地方,请告诉我,我会尽力填写任何细节。

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();
    }
}

3 个答案:

答案 0 :(得分:44)

答案 1 :(得分:6)

在锁内再次检查Running

while (Running)
{
    lock(locker)
    {
        if(Running) {
            DoSomething1();
            DoSomething2();
        }
    }
}

您甚至可以将其重写为while(true)...break,这可能更合适。

答案 2 :(得分:0)

为什么不使用状态为boolRunningStoppedStarting的枚举,而不是使用Running Stopping。 }?

这样,当Running设置为Stopping时,您就会脱离循环,并进行处置。完成后,Running将设置为Stopped。当OnQuit()将Running设置为Stopped时,它将继续并退出。

编辑:这是代码,快速而肮脏,未经过测试等等。

public class SomeThread : IDisposable 
{ 
    private object locker = new object(); 
    private RunState running = RunState.Stopped;

    public enum RunState
    {
        Stopped,
        Starting,
        Running,
        Stopping,
    }

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

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

        Dispose();

    } 

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

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

    public void Dispose() 
    { 
        lock (locker) 
        {    
            Dispose1(); 
            Dispose2(); 
        } 
        Running = RunState.Stopped;
    } 

    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 = SomeThread.RunState.Stopping; 
        while (st.Running == SomeThread.RunState.Stopping) 
        {                 
            // Do something while waiting for the other thread.
        }  

        Exit(); 
    } 
}