让我们尝试使用示例类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();
}
}
答案 0 :(得分:44)
答案 1 :(得分:6)
在锁内再次检查Running
:
while (Running)
{
lock(locker)
{
if(Running) {
DoSomething1();
DoSomething2();
}
}
}
您甚至可以将其重写为while(true)...break
,这可能更合适。
答案 2 :(得分:0)
为什么不使用状态为bool
,Running
,Stopped
和Starting
的枚举,而不是使用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();
}
}